Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Challenge: 2D Tank

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!

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();
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List