NOGDUS

Articles, Tutorials, and other things. => Allegro Game Programming => : Richard Marks May 08, 2010, 10:58:11 AM



: Roids version 1.0
: Richard Marks May 08, 2010, 10:58:11 AM
Pretty much just a code dump for now. I gotta go to work and don't have time to break this down into a tutorial yet.
Enjoy.
:
/*
Roids.cpp
'Roids! 1.0
A simple Asteroids clone in C/C++
(C) 2010, Richard Marks

Features in this version:
* Ship Flight Physics
* Animated Ship
* Graphics created procedurally (no external resources)
*/

// link to allegro on MSVC
#if defined(_WIN32) || defined(WIN32)
#pragma comment(lib, "alleg.lib")
#endif

#include <allegro.h>
#include <math.h>

BITMAP* backBuffer;

/*
player variables

prefix with "player"

X, Y - the position of the upperleft corner of the sprite
XV, YV - the velocity of the ship
R - the rotation angle in radians
Image - the current graphic for the ship to draw

FrameNoThrust - the graphic template for the ship with no thrusters
FrameThrust - the graphic template for the ship with thrusters
*/
float playerX, playerY, playerXV, playerYV, playerR;
BITMAP* playerImage;
BITMAP* playerFrameNoThrust;
BITMAP* playerFrameThrust;

bool LoadContent()
{
const int WHITE = makecol(0xFF, 0xFF, 0xFF);
const int TRANSPARENT = makecol(0xFF, 0x00, 0xFF);

// create the player graphics
const int playerWidth = 48;
const int playerHeight = 24;

playerFrameNoThrust = create_bitmap(playerWidth, playerHeight);
playerFrameThrust = create_bitmap(playerWidth, playerHeight);
clear_to_color(playerFrameNoThrust, TRANSPARENT);
clear_to_color(playerFrameThrust, TRANSPARENT);

// draw the ship with no thruster
const int shipWidth = (playerWidth / 5) * 4;
const int thrustOffset = (playerHeight / 4) * 3;
line(playerFrameNoThrust, playerWidth - shipWidth, 0, playerWidth - 1, playerHeight / 2, WHITE);
line(playerFrameNoThrust, playerWidth - shipWidth, 0, playerWidth - shipWidth, playerHeight - 1, WHITE);
line(playerFrameNoThrust, playerWidth - shipWidth, playerHeight - 1, playerWidth - 1, playerHeight / 2, WHITE);

// copy the ship image to the shp with thruster and draw the thruster
blit(playerFrameNoThrust, playerFrameThrust, 0, 0, 0, 0, playerWidth, playerHeight);
triangle(playerFrameThrust,
0, playerHeight / 2,
playerWidth - shipWidth, thrustOffset,
playerWidth - shipWidth, playerHeight - (thrustOffset + 1), WHITE);

// start the player with the no thruster image
playerImage = playerFrameNoThrust;

// start the player in the center of the screen
playerX = backBuffer->w / 2;
playerY = backBuffer->h / 2;
playerX -= playerImage->w / 2;
playerY -= playerImage->h / 2;

// no rotation to start
playerR = 0.0f;

// not moving
playerXV = 0.0f;
playerYV = 0.0f;

return true;
}

void UpdateFrame()
{
const float maxRotation = 6.28318531f;
const float minRotation = -maxRotation;
const float rotationSpeed = 0.05f;
const float accelerationSpeed = 0.13f;
const float maxVelocity = 10.0f;
const float minVelocity = -maxVelocity;
const float dragForce = 0.02f;

// if the up arrow is held down
if (key[KEY_UP])
{
// change the player image to show the thruster
playerImage = playerFrameThrust;

// accelerate in the direction of rotation
playerXV += (float)(cos(playerR) * accelerationSpeed);
playerYV += (float)(sin(playerR) * accelerationSpeed);

// make sure we don't accelerate too much
if (playerXV > maxVelocity) { playerXV = maxVelocity; }
if (playerXV < minVelocity) { playerXV = minVelocity; }
if (playerYV > maxVelocity) { playerYV = maxVelocity; }
if (playerYV < minVelocity) { playerYV = minVelocity; }
}
else // if the up arrow is not held down
{
// change the player image to not show the thruster
playerImage = playerFrameNoThrust;

// apply some dragging force to slow the ship down gradually
if (playerXV < 0.0f) { playerXV += dragForce; }
if (playerXV > 0.0f) { playerXV -= dragForce; }
if (playerYV < 0.0f) { playerYV += dragForce; }
if (playerYV > 0.0f) { playerYV -= dragForce; }
}

// if the left arrow is held down
if (key[KEY_LEFT])
{
// rotate the player counter clockwise
playerR -= rotationSpeed;
if (playerR < minRotation)
{
playerR = maxRotation;
}
}
else if (key[KEY_RIGHT]) // if the right arrow is held down
{
// rotate the player clockwise
playerR += rotationSpeed;
if (playerR > maxRotation)
{
playerR = minRotation;
}
}

// apply the player velocity to the position to make the ship move
playerX += playerXV;
playerY += playerYV;

// warp the player to opposing edges of the screen
if (playerX < -playerImage->w) { playerX = backBuffer->w; }
if (playerX > backBuffer->w) { playerX = -playerImage->w; }
if (playerY < -playerImage->h) { playerY = backBuffer->h; }
if (playerY > backBuffer->h) { playerY = -playerImage->h; }
}

// draws a sprite rotated at the spefied angle at the specified position
// angle needs to be in degrees
void DrawSpriteRotated(BITMAP* sprite, BITMAP* target, int x, int y, int angle)
{
if (!sprite || !target) { return; }
fixed rotation = ftofix((0.711 * (float)angle));
BITMAP* t = create_bitmap(sprite->w, sprite->h);
blit(sprite, t, 0, 0, 0, 0, t->w, t->h);
rotate_sprite(target, t, x, y, rotation);
destroy_bitmap(t);
}

void RenderFrame()
{
clear_bitmap(backBuffer);

DrawSpriteRotated(playerImage, backBuffer, playerX, playerY, playerR * 57.2957795f);

blit(backBuffer, screen, 0, 0, 0, 0, backBuffer->w, backBuffer->h);
}

void UnloadContent()
{
destroy_bitmap(playerFrameNoThrust);
destroy_bitmap(playerFrameThrust);
}

// everything below is just a small allegro framework app to host the game
static volatile int timerTickCount = 0;
static volatile bool mainThreadIsRunning = true;

static void OnTimerTickEvent()
{
timerTickCount++;
}
END_OF_FUNCTION(OnTimerTickEvent)

static void OnCloseButtonClickEvent()
{
mainThreadIsRunning = false;
}
END_OF_FUNCTION(OnCloseButtonClickEvent)

int main(int argc, char* argv[])
{
allegro_init();
install_keyboard();
install_timer();
set_color_depth(24);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
backBuffer = create_bitmap(SCREEN_W, SCREEN_H);
set_window_title("Roids v1.0 (C) 2010, Richard Marks");
LOCK_FUNCTION(OnCloseButtonClickEvent);
LOCK_FUNCTION(OnTimerTickEvent);
LOCK_VARIABLE(timerTickCount);
set_close_button_callback(OnCloseButtonClickEvent);
install_int_ex(OnTimerTickEvent, BPS_TO_TIMER(30));
srand(time(0));
if (!LoadContent())
{
return 1;
}
while(mainThreadIsRunning)
{
if(timerTickCount > 0)
{
while(timerTickCount > 0)
{
if (keyboard_needs_poll())
{
poll_keyboard();
}
if (key[KEY_ESC]) { mainThreadIsRunning = false; }
UpdateFrame();
timerTickCount--;
}
RenderFrame();
}
else
{
rest(1);
}
}
UnloadContent();
destroy_bitmap(backBuffer);
return 0;
}
END_OF_MAIN()


Sorry, the copyright must be in the template.
Please notify this forum's administrator that this site is missing the copyright message for SMF so they can rectify the situation. Display of copyright is a legal requirement. For more information on this please visit the Simple Machines website.