1
Name:
Anonymous
2010-05-14 15:43
The Challenge:
|---->Program a 2d tank application in the language of your choice that adheres to the following :
#-The tank must rotate using the left and right directional keys.
#-The tank must loosely resemble a tank.
#-The tank must move forward or backward respectively from the direction it is facing using the up and down directional keys.
#-Pressing spacebar must fire a 'shot' in the direction the tank is facing.
#-The perspective of the user must be fixed and facing down at the tank.
#-The tank, shot, and ground must each have their own color. (all shots may have the same color)
<------You have 24 hours!------>
GET TO WORK!
153
Name:
Anonymous
2010-05-20 21:48
#include <SDL/SDL.h>
#include <OpenGL/gl.h>
#include <iostream>
#include <list>
#include <math.h>
#include "Sound.h"
#define square(x) ((x) * (x))
enum Type {kSprite, kObstacle, kLaser, kTank};
using namespace std;
list<struct Sprite*> gSprites;
unsigned char *gKeys;
float gTime = 0.0; // time in seconds
float gTimeIncrement;
struct Point{
float x, y;
};
// should draw in range -1 to 1
struct Sprite{
float x, y;
float oldX, oldY;
float angle;
float size;
float speed;
float turn;
int player; // 0 is non-player sprite
Type type;
void MoveTo(float newX, float newY){
oldX = x, oldY = y;
x = newX, y = newY;
}
void UndoMove(){ x = oldX, y = oldY; }
float Speed() { return speed * gTimeIncrement; }
float Turn() { return turn * gTimeIncrement; }
void Forward(float distance) {
MoveTo(x + distance * sin(angle),
y + distance * cos(angle));
}
// translate to global coordinates
Point Vector(float pX, float pY){
Point p;
float sine = sin(angle), cosine = cos(angle);
p.x = size * (pY * sine + pX * cosine);
p.y = size * (pY * cosine - pX * sine);
return p;
}
Point Global(float pX, float pY){
Point p;
float sine = sin(angle), cosine = cos(angle);
p.x = size * (pY * sine + pX * cosine) + x;
p.y = size * (pY * cosine - pX * sine) + y;
return p;
}
virtual void Draw() {}
virtual void Move() { Forward(Speed()); }
virtual void Collision(Sprite *sprite) {}
Sprite(){
x = 0, y = 0;
angle = 0, size = 10;
speed = 0, turn = 4;
player = 0, type = kSprite;
}
};
struct Maze : Sprite{
virtual void Draw(){
glLineWidth(10.0);
glBegin(GL_LINE_STRIP);
glColor3f(0,1,0);
glVertex2f(-99,-74);
glVertex2f(99,-74);
glVertex2f(99,74);
glVertex2f(-99,74);
glVertex2f(-99,-74);
glEnd();
}
Maze(){ size = 1; }
};
struct Obstacle : Sprite{
virtual void Draw(){
float i;
glLineWidth(3);
glBegin(GL_LINE_STRIP);
glColor3f(0,1,0);
for(i = 0; i < 2 * M_PI; i += .4)
glVertex2f(cos(i),sin(i));
glVertex2f(cos(2 * M_PI), sin(2 * M_PI));
glEnd();
}
Obstacle(float pX, float pY, float theSize){
x = pX, y = pY, size = theSize, type = kObstacle;
}
};
struct Laser : Sprite{
float decay; // invisible once decay == 0
bool bounced; // only bounces once
virtual void Move() {
if(decay <= 0) gSprites.remove(this);
decay -= gTimeIncrement * (bounced ? .6 : .3);
Sprite::Move();
}
virtual void Draw(){
glLineWidth(5.0);
glBegin(GL_LINES);
glColor4f(1, .5, 0, decay);
glVertex2f(0,-1);
glColor4f(1, 1, 0, decay);
glVertex2f(0,1);
glEnd();
}
virtual void Collision(Sprite *s){
if(!bounced){
switch(s->type){
case kTank:
if(s->player != player){
Point impact = Vector(0,.02);
s->x += impact.x;
s->y += impact.y;
}
else break;
case kObstacle:
angle += M_PI + ((rand() %101) - 50.0) / 50.0;
bounced = true;
};
}
}
Laser(int thePlayer, Point p, float a){
x = p.x, y = p.y, size = 10,
angle = a, speed = 80;
player = thePlayer, type = kLaser;
decay = 1.0, bounced = false;
}
};
struct Tank : Sprite{
int fireAngle; // 0,1, or 2
int soundChannel;
void ShootLaser() {
float laserAngle = ((rand() % 41) - 20.0) / 200.0 + angle;
gSprites.push_back(new Laser(player,Global(0,.7),laserAngle));
if(soundChannel == -1 || !IsPlaying(soundChannel));
soundChannel = PlaySound("laser2");
}
virtual void Draw(){
glBegin(GL_TRIANGLES);
glColor3f(0, .5, 1);
glVertex2f(-1, -1);
glVertex2f(1, -1);
glColor3f(0,1,1);
glVertex2f(0,1);
glEnd();
}
virtual void Collision(Sprite *sprite){
if(sprite->type == kObstacle) UndoMove();
}
Tank(){
size = 7; speed = 40; type = kTank, soundChannel = -1;
}
};
struct Player : Tank{
virtual void Move(){
if(player == 1){
if(gKeys[SDLK_RIGHT]) angle += Turn();
if(gKeys[SDLK_LEFT]) angle -= Turn();
if(gKeys[SDLK_UP]) Forward(Speed());
if(gKeys[SDLK_DOWN]) Forward(-Speed());
if(gKeys[SDLK_SPACE]) ShootLaser();
}
if(player == 2){
if(gKeys[SDLK_e]) angle += Turn();
if(gKeys[SDLK_a]) angle -= Turn();
if(gKeys[SDLK_COMMA]) Forward(Speed());
if(gKeys[SDLK_o]) Forward(-Speed());
if(gKeys[SDLK_TAB]) ShootLaser();
}
}
Player(int playerNumber){
player = playerNumber;
if(player == 1) x = 80, angle -= M_PI / 2.0;
if(player == 2) x = -80, angle += M_PI / 2.0;
}
};
int gDone;// = 0;
void MoveSprites();
void DetectCollisions();
void DrawSprites();
int SDL_main(int argc,char* argv[])
{
SDL_Surface *screen;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
InitializeSound();
LoadSounds();
screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL/* | SDL_FULLSCREEN*/);
glViewport(0, 0, screen->w, screen->h);
glOrtho(-100, 100, -75, 75, 0, 1);
glClearColor(0, 0, 0, 1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glEnable(GL_LINE_SMOOTH);
gSprites.push_back(new Maze());
gSprites.push_back(new Obstacle(50,40,20));
gSprites.push_back(new Obstacle(-30,-10,30));
gSprites.push_back(new Obstacle(60,-20,10));
gSprites.push_back(new Player(1));
gSprites.push_back(new Player(2));
while(!gDone){
if(!SDL_PollEvent(&event)){
gKeys = SDL_GetKeyState(NULL);
gTimeIncrement = (double)SDL_GetTicks() / (double)1000.0 - gTime;
gTime += gTimeIncrement;
MoveSprites();
DetectCollisions();
DrawSprites();
SDL_Delay(15);
continue;
}
switch(event.type){
case SDL_MOUSEBUTTONDOWN:
gDone = 1;
break;
}
}
SDL_Quit();
return 0;
}
void MoveSprites()
{
list<Sprite*>::iterator i;
for(i = gSprites.begin(); i != gSprites.end(); ++i)
(*i)->Move();
}
void DetectCollisions()
{
list<Sprite*>::iterator i;
//cerr << "@";
for(i = gSprites.begin(); i != gSprites.end(); ++i){
Sprite *sprite = (*i);
list<Sprite*>::iterator i2 = i;
//cerr << ".";
for(++i2; i2 != gSprites.end(); ++i2){
Sprite *sprite2 = (*i2);
float dx = sprite2->x - sprite->x;
float dy = sprite2->y - sprite->y;
//cerr << "!";
// first objects are probably more permanent
// (bullets might want to delete themselves on collision)
if(square(dx) + square(dy) <= square(sprite->size + sprite2->size)){
//cerr << "W";
sprite->Collision(sprite2);
sprite2->Collision(sprite);
}
}
}
}
void DrawSprites()
{
list<Sprite*>::iterator i;
glClear(GL_COLOR_BUFFER_BIT);
for(i = gSprites.begin(); i != gSprites.end(); ++i){
Sprite *sprite = *i;
float spriteSize = sprite->size;
glPushMatrix();
glTranslatef(sprite->x, sprite->y, 0);
glRotatef(180.0 * sprite->angle / M_PI, 0, 0, -1);
glScalef(spriteSize, spriteSize, spriteSize);
sprite->Draw();
glPopMatrix();
}
SDL_GL_SwapBuffers();
}