From bb62b196e08be48e21db5c0b383fab371a351dd1 Mon Sep 17 00:00:00 2001 From: nick <nick@a97b1542-0b21-0410-a459-e47997c36f34> Date: Sat, 15 Mar 2008 17:06:58 +0000 Subject: [PATCH] Big refactoring git-svn-id: http://svn.nickg.me.uk/work/lander/trunk@304 a97b1542-0b21-0410-a459-e47997c36f34 --- src/Game.cpp | 322 +++++++++++++++------------------------------ src/Lander.hpp | 229 +++++++++++++++----------------- src/Makefile.am | 3 +- src/ObjectGrid.cpp | 61 ++++----- src/Ship.cpp | 117 ++++++++++++++++ src/Ship.hpp | 51 +++++++ src/Viewport.cpp | 70 ++++++++++ src/Viewport.hpp | 46 +++++++ 8 files changed, 523 insertions(+), 376 deletions(-) create mode 100644 src/Ship.cpp create mode 100644 src/Ship.hpp create mode 100644 src/Viewport.cpp create mode 100644 src/Viewport.hpp diff --git a/src/Game.cpp b/src/Game.cpp index f845797..ea5ee40 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -62,7 +62,11 @@ const Point Game::hotspots[] = {{1, 31}, {1, 26}, {3, 14}, {15, 0}, * Sets the inital state of the Game object. */ Game::Game() - : hasloaded(false), bThrusting(false), surface(NULL), state(gsNone) + : hasloaded(false), + bThrusting(false), + surface(NULL), + state(gsNone), + ship(&viewport) { } @@ -79,8 +83,6 @@ void Game::Load() // Load textures if (!hasloaded) { - // Load textures - uShipTexture = opengl.LoadTextureAlpha(g_pData, "Ship.bmp"); uStarTexture = opengl.LoadTextureAlpha(g_pData, "Star.bmp"); uFadeTexture = opengl.LoadTexture(g_pData, "Fade.bmp"); uLevComTexture = opengl.LoadTextureAlpha(g_pData, "LevelComplete.bmp"); @@ -127,18 +129,14 @@ void Game::Load() snprintf(buf, TEX_NAME_LEN, "mine%d.bmp", i*5); uMineTexture[i] = opengl.LoadTextureAlpha(g_pData, buf); } - + + Ship::Load(); LandingPad::Load(); // Toggle loaded flag hasloaded = true; } - // Create the ship - ship.tq.width = 32; - ship.tq.height = 32; - ship.tq.uTexture = uShipTexture; - // Create the fade fade.x = 0; fade.y = 0; @@ -195,9 +193,6 @@ void Game::Load() paused.height = 64; paused.uTexture = uPausedTexture; - // Set default values - nViewAdjustX = 0; - nViewAdjustY = 0; starrotate = 0.0f; death_timeout = 0; state = gsNone; @@ -257,8 +252,8 @@ void Game::Process() if ((input.GetKeyState(SDLK_UP) || input.QueryJoystickButton(1)) && fuel > 0 && state == gsInGame) { // Thrusting - ship.flSpeedX += SHIP_SPEED * (float)sin(ship.angle*(PI/180)); - ship.flSpeedY -= SHIP_SPEED * (float)cos(ship.angle*(PI/180)); + ship.speedX += SHIP_SPEED * (float)sin(ship.angle*(PI/180)); + ship.speedY -= SHIP_SPEED * (float)cos(ship.angle*(PI/180)); bThrusting = true; fuel--; } @@ -300,17 +295,17 @@ void Game::Process() // Move only if not in game over (prevent bugs) if (state == gsInGame || state == gsExplode) { // Apply gravity - ship.flSpeedY += flGravity; + ship.speedY += flGravity; // Move the ship (and exhaust and explosion) - ship.xpos += ship.flSpeedX; - ship.ypos += ship.flSpeedY; + ship.xpos += ship.speedX; + ship.ypos += ship.speedY; exhaust.xpos = ship.xpos + ship.tq.width/2 - (ship.tq.width/2)*(float)sin(ship.angle*(PI/180)); exhaust.ypos = ship.ypos + ship.tq.height/2 + (ship.tq.height/2)*(float)cos(ship.angle*(PI/180)); - exhaust.yg = ship.flSpeedY + (flGravity * 10); - exhaust.xg = ship.flSpeedX; + exhaust.yg = ship.speedY + (flGravity * 10); + exhaust.xg = ship.speedX; explosion.xpos = ship.xpos + ship.tq.width/2; explosion.ypos = ship.ypos + ship.tq.height/2; } @@ -394,19 +389,19 @@ void Game::Process() // Check bounds if (ship.xpos <= 0.0f) { ship.xpos = 0.0f; - ship.flSpeedX *= -0.5f; + ship.speedX *= -0.5f; } - else if (ship.xpos + ship.tq.width > levelwidth) { - ship.xpos = (float)(levelwidth - ship.tq.width); - ship.flSpeedX *= -0.5f; + else if (ship.xpos + ship.tq.width > viewport.GetLevelWidth()) { + ship.xpos = (float)(viewport.GetLevelWidth() - ship.tq.width); + ship.speedX *= -0.5f; } if (ship.ypos <= 0.0f) { ship.ypos = 0.0f; - ship.flSpeedY *= -0.5f; + ship.speedY *= -0.5f; } - else if (ship.ypos + ship.tq.height > levelheight) { - ship.ypos = (float)(levelheight - ship.tq.height); - ship.flSpeedY *= -0.5f; + else if (ship.ypos + ship.tq.height > viewport.GetLevelHeight()) { + ship.ypos = (float)(viewport.GetLevelHeight() - ship.tq.height); + ship.speedY *= -0.5f; // Bug fix if (state == gsExplode) { @@ -418,31 +413,23 @@ void Game::Process() // Calculate view adjusts int centrex = (int)ship.xpos + (ship.tq.width/2); int centrey = (int)ship.ypos + (ship.tq.height/2); - nViewAdjustX = centrex - (opengl.GetWidth()/2); - nViewAdjustY = centrey - (opengl.GetHeight()/2); - if (nViewAdjustX < 0) - nViewAdjustX = 0; - else if (nViewAdjustX > levelwidth - opengl.GetWidth()) - nViewAdjustX = levelwidth - opengl.GetWidth(); - if (nViewAdjustY < 0) - nViewAdjustY = 0; - else if (nViewAdjustY > levelheight - opengl.GetHeight()) - nViewAdjustY = levelheight - opengl.GetHeight(); + viewport.SetXAdjust(centrex - (opengl.GetWidth()/2)); + viewport.SetYAdjust(centrey - (opengl.GetHeight()/2)); // Check for collisions with surface LineSegment l; int lookmin = (int)(ship.xpos/SURFACE_SIZE) - 2; int lookmax = (int)(ship.xpos/SURFACE_SIZE) + 2; if (lookmin < 0) lookmin = 0; - if (lookmax >= levelwidth/SURFACE_SIZE) lookmax = (levelwidth / SURFACE_SIZE) - 1; + if (lookmax >= viewport.GetLevelWidth()/SURFACE_SIZE) lookmax = (viewport.GetLevelWidth() / SURFACE_SIZE) - 1; for (i = lookmin; i <= lookmax; i++) { l.p1.x = i*SURFACE_SIZE; - l.p1.y = levelheight - MAX_SURFACE_HEIGHT + surface[i].points[1].y; + l.p1.y = viewport.GetLevelHeight() - MAX_SURFACE_HEIGHT + surface[i].points[1].y; l.p2.x = (i+1)*SURFACE_SIZE; - l.p2.y = levelheight - MAX_SURFACE_HEIGHT + surface[i].points[2].y; + l.p2.y = viewport.GetLevelHeight() - MAX_SURFACE_HEIGHT + surface[i].points[2].y; // Look through each hot spot and check for collisions - if (HotSpotCollision(ship, l, points, NUM_HOTSPOTS, ship.xpos, ship.ypos)) { + if (ship.HotSpotCollision(l, points, NUM_HOTSPOTS)) { // Collided - see which game state we're in if (state == gsInGame) { bool bLanded = false; @@ -455,7 +442,7 @@ void Game::Process() // We landed int nDAngle = ((int)ship.angle) % 360; if ((nDAngle >= 350 || nDAngle <= 30) - && ship.flSpeedY < LAND_SPEED && !nKeysRemaining) { + && ship.speedY < LAND_SPEED && !nKeysRemaining) { // Landed safely bLanded = true; nPadOn = k; @@ -488,7 +475,7 @@ void Game::Process() BounceShip(); // See if we need to stop the madness - if (state == gsExplode && ship.flSpeedY*-1 < 0.05f) { + if (state == gsExplode && ship.speedY*-1 < 0.05f) { state = gsDeathWait; death_timeout = DEATH_TIMEOUT; } @@ -499,7 +486,7 @@ void Game::Process() // Check for collisions with asteroids LineSegment l1, l2; for (i = 0; i < asteroidcount; i++) { - if (ObjectInScreen(asteroids[i].GetXPos(), + if (viewport.ObjectInScreen(asteroids[i].GetXPos(), asteroids[i].GetYPos() + SHIP_START_Y / ObjectGrid::OBJ_GRID_SIZE, asteroids[i].GetWidth(), 4)) { // Look at polys @@ -507,8 +494,8 @@ void Game::Process() l1 = asteroids[i].GetUpBoundary(k); l2 = asteroids[i].GetDownBoundary(k); - if (HotSpotCollision(ship, l1, points, NUM_HOTSPOTS, ship.xpos, ship.ypos) - || HotSpotCollision(ship, l2, points, NUM_HOTSPOTS, ship.xpos, ship.ypos)) { + if (ship.HotSpotCollision(l1, points, NUM_HOTSPOTS) + || ship.HotSpotCollision(l2, points, NUM_HOTSPOTS)) { // Crashed if (state == gsInGame) { // Destroy the ship @@ -519,7 +506,7 @@ void Game::Process() BounceShip(); // See if we need to stop the madness - if (state == gsExplode && ship.flSpeedY*-1 < 0.05f) + if (state == gsExplode && ship.speedY*-1 < 0.05f) { state = gsDeathWait; death_timeout = DEATH_TIMEOUT; @@ -537,9 +524,8 @@ void Game::Process() int dy = gateways[i].vertical ? gateways[i].length : 0; if (gateways[i].timer > GATEWAY_ACTIVE) { - bool collide1 = BoxCollision + bool collide1 = ship.BoxCollision ( - ship, gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE, gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y, ObjectGrid::OBJ_GRID_SIZE, @@ -548,9 +534,8 @@ void Game::Process() NUM_HOTSPOTS ); - bool collide2 = BoxCollision + bool collide2 = ship.BoxCollision ( - ship, (gateways[i].xpos + dx)*ObjectGrid::OBJ_GRID_SIZE, (gateways[i].ypos + dy)*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y, ObjectGrid::OBJ_GRID_SIZE, @@ -572,7 +557,7 @@ void Game::Process() BounceShip(); // See if we need to stop the madness - if (state == gsExplode && ship.flSpeedY*-1 < 0.05f) + if (state == gsExplode && ship.speedY*-1 < 0.05f) { state = gsDeathWait; death_timeout = DEATH_TIMEOUT; @@ -582,9 +567,8 @@ void Game::Process() } else { - bool collide = BoxCollision + bool collide = ship.BoxCollision ( - ship, gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE, gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y, (dx + 1)*ObjectGrid::OBJ_GRID_SIZE, @@ -614,9 +598,8 @@ void Game::Process() // Check for collisions with mines for (i = 0; i < minecount; i++) { - bool collide = BoxCollision + bool collide = ship.BoxCollision ( - ship, mines[i].xpos*ObjectGrid::OBJ_GRID_SIZE + 3 + mines[i].displace_x, mines[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 6 + mines[i].displace_y, ObjectGrid::OBJ_GRID_SIZE*2 - 6, @@ -638,7 +621,7 @@ void Game::Process() BounceShip(); // See if we need to stop the madness - if (state == gsExplode && -ship.flSpeedY < 0.05f) + if (state == gsExplode && -ship.speedY < 0.05f) { state = gsDeathWait; death_timeout = DEATH_TIMEOUT; @@ -650,9 +633,8 @@ void Game::Process() // See if the player collected a key for (i = 0; i < nKeys; i++) { - bool collide = BoxCollision + bool collide = ship.BoxCollision ( - ship, keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE + 3, keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 3, ObjectGrid::OBJ_GRID_SIZE - 6, @@ -777,7 +759,7 @@ void Game::Process() // Resize the speed bar float flSpeed1 = 30.0f / LAND_SPEED; - int width = (int)((float)ship.flSpeedY * flSpeed1); + int width = (int)((float)ship.speedY * flSpeed1); if (width < 0) width = 0; if (width > 124) @@ -794,23 +776,23 @@ void Game::StartLevel(int level) int i, change, texloop=0, j, k, nPadHere; // Set level size - levelwidth = 2000 + 2*SURFACE_SIZE*level; - levelheight = 1500 + 2*SURFACE_SIZE*level; + viewport.SetLevelWidth(2000 + 2*SURFACE_SIZE*level); + viewport.SetLevelHeight(1500 + 2*SURFACE_SIZE*level); flGravity = GRAVITY; // Create the object grid - int grid_w = levelwidth / ObjectGrid::OBJ_GRID_SIZE; - int grid_h = (levelheight - SHIP_START_Y - MAX_SURFACE_HEIGHT - 100) / ObjectGrid::OBJ_GRID_SIZE; + int grid_w = viewport.GetLevelWidth() / ObjectGrid::OBJ_GRID_SIZE; + int grid_h = (viewport.GetLevelHeight() - SHIP_START_Y - MAX_SURFACE_HEIGHT - 100) / ObjectGrid::OBJ_GRID_SIZE; objgrid.Reset(grid_w, grid_h); // Create background stars - nStarCount = (levelwidth * levelheight) / 10000; + nStarCount = (viewport.GetLevelWidth() * viewport.GetLevelHeight()) / 10000; if (nStarCount > MAX_GAME_STARS) nStarCount = MAX_GAME_STARS; for (i = 0; i < nStarCount; i++) { - stars[i].xpos = (int)(rand()%(levelwidth/20))*20; - stars[i].ypos = (int)(rand()%(levelheight/20))*20; + stars[i].xpos = (int)(rand()%(viewport.GetLevelWidth()/20))*20; + stars[i].ypos = (int)(rand()%(viewport.GetLevelHeight()/20))*20; stars[i].quad.uTexture = uStarTexture; stars[i].quad.width = stars[i].quad.height = rand()%15; } @@ -818,7 +800,7 @@ void Game::StartLevel(int level) // Create the planet surface if (surface) delete[] surface; - surface = new Poly[levelwidth/SURFACE_SIZE]; + surface = new Poly[viewport.GetLevelWidth()/SURFACE_SIZE]; // Generate landing pads nLandingPads = rand()%MAX_PADS + 1; @@ -828,12 +810,12 @@ void Game::StartLevel(int level) bool overlap; do { - index = rand() % (levelwidth / SURFACE_SIZE); + index = rand() % (viewport.GetLevelWidth() / SURFACE_SIZE); length = rand() % MAX_PAD_SIZE + 3; // Check for overlap overlap = false; - if (index + length > (levelwidth / SURFACE_SIZE)) + if (index + length > (viewport.GetLevelWidth() / SURFACE_SIZE)) overlap = true; for (int j = 0; j < i; j++) { @@ -851,11 +833,11 @@ void Game::StartLevel(int level) // Generate surface int surftex = rand()%NUM_SURF_TEX; - for (i = 0; i < levelwidth/SURFACE_SIZE; i++) + for (i = 0; i < viewport.GetLevelWidth()/SURFACE_SIZE; i++) { surface[i].pointcount = 4; surface[i].xpos = i * SURFACE_SIZE; - surface[i].ypos = levelheight - MAX_SURFACE_HEIGHT; + surface[i].ypos = viewport.GetLevelHeight() - MAX_SURFACE_HEIGHT; surface[i].uTexture = uSurfaceTexture[surftex]; surface[i].texX = ((float)texloop)/10; if (texloop++ == 10) @@ -1068,13 +1050,13 @@ void Game::StartLevel(int level) } // Set ship starting position - ship.xpos = (float)levelwidth/2; + ship.xpos = (float)viewport.GetLevelWidth()/2; ship.ypos = SHIP_START_Y - 40; // Reset data ship.angle = 0.0f; - ship.flSpeedX = 0.0f; - ship.flSpeedY = 0.0f; + ship.speedX = 0.0f; + ship.speedY = 0.0f; leveltext_timeout = LEVEL_TEXT_TIMEOUT; // Reset emitters @@ -1109,10 +1091,10 @@ void Game::ExplodeShip() */ void Game::BounceShip() { - ship.flSpeedY *= -1; - ship.flSpeedX *= -1; - ship.flSpeedX /= 2; - ship.flSpeedY /= 2; + ship.speedY *= -1; + ship.speedX *= -1; + ship.speedX /= 2; + ship.speedY /= 2; } @@ -1131,103 +1113,6 @@ void Game::RotatePoints(const Point *pPoints, Point *pDest, int nCount, float an } } -/* Does a collision based on hot spots */ -bool Game::HotSpotCollision(ActiveObject &a, LineSegment &l, Point *points, int nPoints, float dx, float dy) -{ - for (int i = 0; i < nPoints; i++) - { - if (CheckCollision(a, l, dx + points[i].x, dy + points[i].y)) - return true; - } - - return false; -} - -/* - * Works out whether or not an object is visible. - * xpos, ypos -> Grid co-ordinates. - * width, height -> Size of object in grid squares. - */ -bool Game::ObjectInScreen(int xpos, int ypos, int width, int height) -{ - return PointInScreen(xpos * ObjectGrid::OBJ_GRID_SIZE, ypos * ObjectGrid::OBJ_GRID_SIZE, - width * ObjectGrid::OBJ_GRID_SIZE, height * ObjectGrid::OBJ_GRID_SIZE); -} - - -/* - * Works out whether or not a point is visible. - * xpos, ypos -> Absolute co-ordinates. - * width, height -> Size of object. - */ -bool Game::PointInScreen(int xpos, int ypos, int width, int height) -{ - OpenGL &opengl = OpenGL::GetInstance(); - - int sw = opengl.GetWidth(); - int sh = opengl.GetHeight(); - - if (xpos + width > nViewAdjustX && xpos - nViewAdjustX < sw && - ypos + height > nViewAdjustY && ypos - nViewAdjustY < sh) - return true; - else - return false; -} - - -/* Does simple box collision */ -bool Game::BoxCollision(ActiveObject &a, int x, int y, int w, int h, Point *points, int nPoints) -{ - if (!PointInScreen(x, y, w, h)) - return false; - - LineSegment l1(x, y, x + w, y); - LineSegment l2(x + w, y, x + w, y + h); - LineSegment l3(x + w, y + h, x, y + h); - LineSegment l4(x, y + h, x, y); - - return HotSpotCollision(a, l1, points, nPoints, a.xpos, a.ypos) || - HotSpotCollision(a, l2, points, nPoints, a.xpos, a.ypos) || - HotSpotCollision(a, l3, points, nPoints, a.xpos, a.ypos) || - HotSpotCollision(a, l4, points, nPoints, a.xpos, a.ypos); -} - -/* Checks for collision between a vector and a line segment */ -bool Game::CheckCollision(ActiveObject &a, LineSegment &l, float xpos, float ypos) -{ - if (xpos == -1 || ypos == -1) - { - xpos = a.xpos; - ypos = a.ypos; - } - - // Get position after next move - float cX = xpos + a.flSpeedX; - float cY = ypos + a.flSpeedY; - - // Get displacement - float vecX = cX - xpos; - float vecY = cY - ypos; - - // Get line position - float wallX = (float)(l.p2.x - l.p1.x); - float wallY = (float)(l.p2.y - l.p1.y); - - // Work out numerator and denominator (used parametric equations) - float numT = wallX * (ypos - l.p1.y) - wallY * (xpos - l.p1.x); - float numU = vecX * (ypos - l.p1.y) - vecY * (xpos - l.p1.x); - - // Work out denominator - float denom = wallY * (cX - xpos) - wallX * (cY - ypos); - - // Work out u and t - float u = numU / denom; - float t = numT / denom; - - // Collision occured if (0 < t < 1) and (0 < u < 1) - return (t > 0.0f) && (t < 1.0f) && (u > 0.0f) && (u < 1.0f); -} - /* Displays frame to user */ void Game::Display() { @@ -1240,27 +1125,27 @@ void Game::Display() // Draw the stars for (i = 0; i < nStarCount; i++) { - stars[i].quad.x = stars[i].xpos - nViewAdjustX; - stars[i].quad.y = stars[i].ypos - nViewAdjustY; + stars[i].quad.x = stars[i].xpos - viewport.GetXAdjust(); + stars[i].quad.y = stars[i].ypos - viewport.GetYAdjust(); opengl.DrawRotate(&stars[i].quad, starrotate); starrotate += 0.005f; } // Draw the planet surface - for (i = 0; i < levelwidth/SURFACE_SIZE; i++) + for (i = 0; i < viewport.GetLevelWidth()/SURFACE_SIZE; i++) { - surface[i].xpos = i*SURFACE_SIZE - nViewAdjustX; - surface[i].ypos = levelheight - nViewAdjustY - MAX_SURFACE_HEIGHT; + surface[i].xpos = i*SURFACE_SIZE - viewport.GetXAdjust(); + surface[i].ypos = viewport.GetLevelHeight() - viewport.GetYAdjust() - MAX_SURFACE_HEIGHT; opengl.Draw(&surface[i]); } // Draw the asteroids for (i = 0; i < asteroidcount; i++) { - if (ObjectInScreen(asteroids[i].GetXPos(), asteroids[i].GetYPos() + SHIP_START_Y / ObjectGrid::OBJ_GRID_SIZE, + if (viewport.ObjectInScreen(asteroids[i].GetXPos(), asteroids[i].GetYPos() + SHIP_START_Y / ObjectGrid::OBJ_GRID_SIZE, asteroids[i].GetWidth(), asteroids[i].GetHeight())) { - asteroids[i].Draw(nViewAdjustX, nViewAdjustY); + asteroids[i].Draw(viewport.GetXAdjust(), viewport.GetYAdjust()); } } @@ -1269,8 +1154,8 @@ void Game::Display() { if (keys[i].active) { - keys[i].frame[keys[i].current].x = keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX; - keys[i].frame[keys[i].current].y = keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustY + SHIP_START_Y; + keys[i].frame[keys[i].current].x = keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(); + keys[i].frame[keys[i].current].y = keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetYAdjust() + SHIP_START_Y; opengl.Draw(&keys[i].frame[keys[i].current]); if (--keys[i].rotcount == 0) { @@ -1283,8 +1168,8 @@ void Game::Display() { if (keys[i].alpha > 0.0f) { - keys[i].frame[keys[i].current].x = keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX; - keys[i].frame[keys[i].current].y = keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustY + SHIP_START_Y; + keys[i].frame[keys[i].current].x = keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(); + keys[i].frame[keys[i].current].y = keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetYAdjust() + SHIP_START_Y; opengl.DrawBlend(&keys[i].frame[keys[i].current], keys[i].alpha); keys[i].alpha -= 0.02f; if (--keys[i].rotcount == 0) @@ -1301,20 +1186,20 @@ void Game::Display() for (i = 0; i < gatewaycount; i++) { // Draw first sphere - gateways[i].icon.x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX; - gateways[i].icon.y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - nViewAdjustY; + gateways[i].icon.x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(); + gateways[i].icon.y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - viewport.GetYAdjust(); opengl.Draw(&gateways[i].icon); // Draw second sphere if (gateways[i].vertical) { - gateways[i].icon.x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX; - gateways[i].icon.y = (gateways[i].ypos+gateways[i].length)*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - nViewAdjustY; + gateways[i].icon.x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(); + gateways[i].icon.y = (gateways[i].ypos+gateways[i].length)*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - viewport.GetYAdjust(); } else { - gateways[i].icon.x = (gateways[i].xpos+gateways[i].length)*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX; - gateways[i].icon.y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - nViewAdjustY; + gateways[i].icon.x = (gateways[i].xpos+gateways[i].length)*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(); + gateways[i].icon.y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - viewport.GetYAdjust(); } opengl.Draw(&gateways[i].icon); @@ -1341,27 +1226,27 @@ void Game::Display() glColor3f(r, g, b); if (gateways[i].vertical) { - x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE + 16 + deviation - nViewAdjustX; - y = (gateways[i].ypos+k)*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 16 - nViewAdjustY; + x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE + 16 + deviation - viewport.GetXAdjust(); + y = (gateways[i].ypos+k)*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 16 - viewport.GetYAdjust(); glVertex2i(x, y); if (k == gateways[i].length-1) deviation = 0; else deviation += rand()%20 - 10; - x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE + 16 + deviation - nViewAdjustX; + x = gateways[i].xpos*ObjectGrid::OBJ_GRID_SIZE + 16 + deviation - viewport.GetXAdjust(); y += ObjectGrid::OBJ_GRID_SIZE; glVertex2i(x, y); } else { - x = (gateways[i].xpos+k)*ObjectGrid::OBJ_GRID_SIZE + 16 - nViewAdjustX; - y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 16 + deviation - nViewAdjustY; + x = (gateways[i].xpos+k)*ObjectGrid::OBJ_GRID_SIZE + 16 - viewport.GetXAdjust(); + y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 16 + deviation - viewport.GetYAdjust(); glVertex2i(x, y); if (k == gateways[i].length-1) deviation = 0; else deviation += rand()%20 - 10; - y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 16 + deviation - nViewAdjustY; + y = gateways[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y + 16 + deviation - viewport.GetYAdjust(); x += ObjectGrid::OBJ_GRID_SIZE; glVertex2i(x, y); } @@ -1378,8 +1263,8 @@ void Game::Display() // Draw mines for (i = 0; i < minecount; i++) { - mines[i].frame[mines[i].current].x = mines[i].xpos*ObjectGrid::OBJ_GRID_SIZE + mines[i].displace_x - nViewAdjustX; - mines[i].frame[mines[i].current].y = mines[i].ypos*ObjectGrid::OBJ_GRID_SIZE + mines[i].displace_y - nViewAdjustY + SHIP_START_Y; + mines[i].frame[mines[i].current].x = mines[i].xpos*ObjectGrid::OBJ_GRID_SIZE + mines[i].displace_x - viewport.GetXAdjust(); + mines[i].frame[mines[i].current].y = mines[i].ypos*ObjectGrid::OBJ_GRID_SIZE + mines[i].displace_y - viewport.GetYAdjust() + SHIP_START_Y; opengl.Draw(&mines[i].frame[mines[i].current]); if (--mines[i].rotcount == 0) { @@ -1405,10 +1290,10 @@ void Game::Display() { glLoadIdentity(); glBegin(GL_QUADS); - glVertex2i(x*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX, y*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustY + SHIP_START_Y); - glVertex2i((x+1)*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX, y*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustY + SHIP_START_Y); - glVertex2i((x+1)*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX, (y+1)*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustY + SHIP_START_Y); - glVertex2i(x*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX, (y+1)*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustY + SHIP_START_Y); + glVertex2i(x*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(), y*ObjectGrid::OBJ_GRID_SIZE - viewport.GetYAdjust() + SHIP_START_Y); + glVertex2i((x+1)*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(), y*ObjectGrid::OBJ_GRID_SIZE - viewport.GetYAdjust() + SHIP_START_Y); + glVertex2i((x+1)*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(), (y+1)*ObjectGrid::OBJ_GRID_SIZE - viewport.GetYAdjust() + SHIP_START_Y); + glVertex2i(x*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(), (y+1)*ObjectGrid::OBJ_GRID_SIZE - viewport.GetYAdjust() + SHIP_START_Y); glEnd(); } } @@ -1418,15 +1303,14 @@ void Game::Display() // Draw the landing pads for (i = 0; i < nLandingPads; i++) { - pads[i].Draw(nViewAdjustX, nViewAdjustY, levelheight, nKeysRemaining > 0); + pads[i].Draw(viewport.GetXAdjust(), viewport.GetYAdjust(), viewport.GetLevelHeight(), nKeysRemaining > 0); } - // Draw the ship - ship.tq.x = (int)ship.xpos - nViewAdjustX; - ship.tq.y = (int)ship.ypos - nViewAdjustY; + // Draw the exhaust + if (bThrusting) { - if (sqrt(ship.flSpeedX*ship.flSpeedX + ship.flSpeedY*ship.flSpeedY) > 2.0f) + if (sqrt(ship.speedX*ship.speedX + ship.speedY*ship.speedY) > 2.0f) { exhaust.NewCluster ( @@ -1434,17 +1318,17 @@ void Game::Display() (int)(exhaust.ypos + (exhaust.ypos - ylast)/2) ); } - exhaust.Draw((float)nViewAdjustX, (float)nViewAdjustY, true); + exhaust.Draw((float)viewport.GetXAdjust(), (float)viewport.GetYAdjust(), true); } else if (state == gsPaused) - exhaust.Draw((float)nViewAdjustX, (float)nViewAdjustY, false, false); + exhaust.Draw((float)viewport.GetXAdjust(), (float)viewport.GetYAdjust(), false, false); else - exhaust.Draw((float)nViewAdjustX, (float)nViewAdjustY, false); + exhaust.Draw((float)viewport.GetXAdjust(), (float)viewport.GetYAdjust(), false); if (state != gsDeathWait && state != gsGameOver && state != gsFadeToDeath && state != gsFadeToRestart) { - opengl.DrawRotate(&ship.tq, ship.angle); + ship.Display(); } xlast = exhaust.xpos; @@ -1453,7 +1337,7 @@ void Game::Display() // Draw the explosion if necessary if (state == gsExplode) { - explosion.Draw((float)nViewAdjustX, (float)nViewAdjustY, true); + explosion.Draw((float)viewport.GetXAdjust(), (float)viewport.GetYAdjust(), true); opengl.Colour(0.0f, 1.0f, 0.0f); ft.Print ( @@ -1466,14 +1350,14 @@ void Game::Display() else if (state == gsDeathWait || state == gsGameOver || state == gsFadeToDeath || state == gsFadeToRestart) { - explosion.Draw((float)nViewAdjustX, (float)nViewAdjustY, false); + explosion.Draw((float)viewport.GetXAdjust(), (float)viewport.GetYAdjust(), false); } // Draw the arrows for (i = 0; i < nKeys; i++) { - if (keys[i].active && !ObjectInScreen(keys[i].xpos, keys[i].ypos + SHIP_START_Y / ObjectGrid::OBJ_GRID_SIZE, 1, 1)) { - int ax = keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE - nViewAdjustX; - int ay = keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - nViewAdjustY; + if (keys[i].active && !viewport.ObjectInScreen(keys[i].xpos, keys[i].ypos + SHIP_START_Y / ObjectGrid::OBJ_GRID_SIZE, 1, 1)) { + int ax = keys[i].xpos*ObjectGrid::OBJ_GRID_SIZE - viewport.GetXAdjust(); + int ay = keys[i].ypos*ObjectGrid::OBJ_GRID_SIZE + SHIP_START_Y - viewport.GetYAdjust(); double angle = 0.0; if (ax < 0) { diff --git a/src/Lander.hpp b/src/Lander.hpp index 020ebc5..caeb7fa 100644 --- a/src/Lander.hpp +++ b/src/Lander.hpp @@ -31,8 +31,10 @@ #include "Menu.hpp" #include "HighScores.hpp" +#include "Viewport.hpp" #include "ObjectGrid.hpp" #include "Asteroid.hpp" +#include "Ship.hpp" // Different fonts to be loaded enum FontType { ftNormal, ftBig, ftScore, ftHollow, ftScoreName, ftLarge }; @@ -45,154 +47,135 @@ enum DIRECTIONS { UP, RIGHT, DOWN, LEFT, NODIR }; #define MAX(a, b) (a > b ? a : b) - -/* An object that can move about the screen */ -class ActiveObject -{ -public: - ActiveObject() : xpos(0), ypos(0), flSpeedX(0), flSpeedY(0), angle(0) - { } - float xpos, ypos; - float flSpeedX, flSpeedY, angle; - TextureQuad tq; -}; - - /* * A landing pad where the player tries to land. */ class LandingPad { public: - LandingPad() {} - ~LandingPad() {} + LandingPad() {} + ~LandingPad() {} - static void Load(); + static void Load(); - void Reset(int index, int length); - void Draw(int viewadjust_x, int viewadjust_y, int levelheight, bool locked); - void SetYPos(int ypos) { this->ypos = ypos; } + void Reset(int index, int length); + void Draw(int viewadjust_x, int viewadjust_y, int levelheight, bool locked); + void SetYPos(int ypos) { this->ypos = ypos; } - int GetLength() const { return length; } - int GetIndex() const { return index; } + int GetLength() const { return length; } + int GetIndex() const { return index; } private: - TextureQuad quad; - int index, length, ypos; + TextureQuad quad; + int index, length, ypos; - static Texture s_landtex, s_nolandtex; + static Texture s_landtex, s_nolandtex; }; class Game : public Screen { public: - Game(); - virtual ~Game(); + Game(); + virtual ~Game(); - void Load(); - void Process(); - void Display(); - void NewGame(); - void StartLevel(int nLevel); + void Load(); + void Process(); + void Display(); + void NewGame(); + void StartLevel(int nLevel); private: - bool CheckCollision(ActiveObject &a, LineSegment &l, float xpos=-1, float ypos=-1); - bool HotSpotCollision(ActiveObject &a, LineSegment &l, Point *points, int nPoints, float dx=0, float dy=0); - bool BoxCollision(ActiveObject &a, int x, int y, int w, int h, Point *points, int nPoints); - void RotatePoints(const Point *pPoints, Point *pDest, int nCount, float angle, int adjustx=0, int adjusty=0); - bool ObjectInScreen(int xpos, int ypos, int width, int height); - bool PointInScreen(int xpos, int ypos, int width, int height); - void BounceShip(); - void ExplodeShip(); - - // Private variables - ActiveObject ship; - int death_timeout, level, fuel, maxfuel, lives; - int nViewAdjustX, nViewAdjustY, levelwidth, levelheight; - bool hasloaded, bThrusting, bDebugMode; - float flGravity, starrotate, fade_alpha, life_alpha; - Explosion explosion; - SmokeTrail exhaust; - Poly *surface; - TextureQuad fade, levcomp, speedmeter, fuelmeter, smallship, gameover, paused; - ColourQuad speedbar; - int score, newscore, nextnewlife; - int countdown_timeout, leveltext_timeout, levelcomp_timeout; - - // Game states - enum GameState { gsNone, gsInGame, gsExplode, gsGameOver, gsDeathWait, - gsFadeIn, gsFadeToDeath, gsFadeToRestart, gsLevelComplete, gsPaused }; - GameState state; - - ObjectGrid objgrid; + + void RotatePoints(const Point *pPoints, Point *pDest, int nCount, float angle, int adjustx=0, int adjusty=0); + void BounceShip(); + void ExplodeShip(); + + Viewport viewport; + Ship ship; + int death_timeout, level, fuel, maxfuel, lives; + bool hasloaded, bThrusting, bDebugMode; + float flGravity, starrotate, fade_alpha, life_alpha; + Explosion explosion; + SmokeTrail exhaust; + Poly *surface; + TextureQuad fade, levcomp, speedmeter, fuelmeter, smallship, gameover, paused; + ColourQuad speedbar; + int score, newscore, nextnewlife; + int countdown_timeout, leveltext_timeout, levelcomp_timeout; + + enum GameState { gsNone, gsInGame, gsExplode, gsGameOver, gsDeathWait, + gsFadeIn, gsFadeToDeath, gsFadeToRestart, gsLevelComplete, gsPaused }; + GameState state; + + ObjectGrid objgrid; - // Number of available _surface textures - static const int NUM_SURF_TEX = 5; - - // Textures - GLuint uStarTexture, uShipTexture, uSurfaceTexture[NUM_SURF_TEX], uSurf2Texture[NUM_SURF_TEX], uFadeTexture; - GLuint uLevComTexture, uSpeedTexture, uBlueKey[18], uRedKey[18], uGreenKey[18], uPinkKey[18], uYellowKey[18]; - GLuint uBlueArrow, uPinkArrow, uRedArrow, uYellowArrow, uGreenArrow; - GLuint uGatewayTexture, uFuelMeterTexture, uFuelBarTexture, uMineTexture[36], uShipSmallTexture; - GLuint uGameOver, uPausedTexture; + // Number of available _surface textures + static const int NUM_SURF_TEX = 5; + + // Textures + GLuint uStarTexture, uSurfaceTexture[NUM_SURF_TEX], uSurf2Texture[NUM_SURF_TEX], uFadeTexture; + GLuint uLevComTexture, uSpeedTexture, uBlueKey[18], uRedKey[18], uGreenKey[18], uPinkKey[18], uYellowKey[18]; + GLuint uBlueArrow, uPinkArrow, uRedArrow, uYellowArrow, uGreenArrow; + GLuint uGatewayTexture, uFuelMeterTexture, uFuelBarTexture, uMineTexture[36], uShipSmallTexture; + GLuint uGameOver, uPausedTexture; - static const int NUM_HOTSPOTS = 8; - Point points[NUM_HOTSPOTS]; - static const Point hotspots[]; + static const int NUM_HOTSPOTS = 8; + Point points[NUM_HOTSPOTS]; + static const Point hotspots[]; - // Stars - static const int MAX_GAME_STARS = 2048; - struct Star - { - TextureQuad quad; - float scale; - int xpos, ypos; - } stars[MAX_GAME_STARS]; - int nStarCount; - - // Landing pads - static const int MAX_PADS = 3; - LandingPad pads[MAX_PADS]; - int nLandingPads; + // Stars + static const int MAX_GAME_STARS = 2048; + struct Star + { + TextureQuad quad; + float scale; + int xpos, ypos; + } stars[MAX_GAME_STARS]; + int nStarCount; + + // Landing pads + static const int MAX_PADS = 3; + LandingPad pads[MAX_PADS]; + int nLandingPads; - // Keys - static const int MAX_KEYS = 5; - struct Key - { - int xpos, ypos; - TextureQuad frame[18], arrow; - int current, rotcount; - float alpha; - bool active; - } keys[MAX_KEYS]; - int nKeysRemaining, nKeys; - - // Asteroids - static const int MAX_ASTEROIDS = 50; - Asteroid asteroids[MAX_ASTEROIDS]; - int asteroidcount; - - // Electric gate things - static const int MAX_GATEWAYS = 4; - static const int MAX_GATEWAY_LENGTH = 10; - struct Gateway - { - int xpos, ypos, length, timer; - bool vertical; - TextureQuad icon; - } gateways[MAX_GATEWAYS]; - int gatewaycount; - - // Space mines - static const int MAX_MINES = 5; - struct Mine - { - int xpos, ypos, current, rotcount, dir, displace_x, displace_y, movedelay; - int movetimeout; - TextureQuad frame[36]; - } mines[MAX_MINES]; - int minecount; + // Keys + static const int MAX_KEYS = 5; + struct Key + { + int xpos, ypos; + TextureQuad frame[18], arrow; + int current, rotcount; + float alpha; + bool active; + } keys[MAX_KEYS]; + int nKeysRemaining, nKeys; + + // Asteroids + static const int MAX_ASTEROIDS = 50; + Asteroid asteroids[MAX_ASTEROIDS]; + int asteroidcount; + + // Electric gate things + static const int MAX_GATEWAYS = 4; + static const int MAX_GATEWAY_LENGTH = 10; + struct Gateway + { + int xpos, ypos, length, timer; + bool vertical; + TextureQuad icon; + } gateways[MAX_GATEWAYS]; + int gatewaycount; + + // Space mines + static const int MAX_MINES = 5; + struct Mine + { + int xpos, ypos, current, rotcount, dir, displace_x, displace_y, movedelay; + int movetimeout; + TextureQuad frame[36]; + } mines[MAX_MINES]; + int minecount; }; #endif diff --git a/src/Makefile.am b/src/Makefile.am index 39526b2..1eb5730 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,7 @@ lander_SOURCES = Main.cpp Lander.hpp Game.cpp \ DataFile.cpp DataFile.hpp File.cpp File.hpp Platform.hpp \ OpenGL.cpp OpenGL.hpp Menu.cpp Menu.hpp Emitter.cpp \ Emitter.hpp Screens.cpp Screens.hpp Strings.hpp \ - ObjectGrid.hpp ObjectGrid.cpp Asteroid.hpp Asteroid.cpp + ObjectGrid.hpp ObjectGrid.cpp Asteroid.hpp Asteroid.cpp \ + Ship.hpp Ship.cpp Viewport.hpp Viewport.cpp dist_pkgdata_DATA = ../lander.dat ../Default_Font.ttf ../Hollow_Font.ttf diff --git a/src/ObjectGrid.cpp b/src/ObjectGrid.cpp index 780cad6..313d6bd 100644 --- a/src/ObjectGrid.cpp +++ b/src/ObjectGrid.cpp @@ -40,15 +40,14 @@ bool ObjectGrid::AllocFreeSpace(int &x, int &y) int timeout = 10000; // Keep generating points until we find a free space - do - { - if (--timeout == 0) - return false; - - x = rand() % width; - y = rand() % height; - } while (grid[x + (y * width)]); - + do { + if (--timeout == 0) + return false; + + x = rand() % width; + y = rand() % height; + } while (grid[x + (y * width)]); + grid[x + (y * width)] = true; return true; @@ -67,31 +66,27 @@ bool ObjectGrid::AllocFreeSpace(int &x, int &y, int width, int height) int timeout = 10000; // Keep generating points until we find a free space - do - { - if (--timeout == 0) - return false; - - x = rand() % (this->width - width); - y = rand() % (this->height - height); - - // Check this position - isOk = true; - for (counter_x = x; counter_x < x + width; counter_x++) - { - for (counter_y = y; counter_y < y + height; counter_y++) - { - if (grid[counter_x + (counter_y * this->width)]) - isOk = false; - } - } - } while (!isOk); - - for (counter_x = x; counter_x < x + width; counter_x++) - { - for (counter_y = y; counter_y < y + height; counter_y++) - grid[counter_x + (counter_y * this->width)] = true; + do { + if (--timeout == 0) + return false; + + x = rand() % (this->width - width); + y = rand() % (this->height - height); + + // Check this position + isOk = true; + for (counter_x = x; counter_x < x + width; counter_x++) { + for (counter_y = y; counter_y < y + height; counter_y++) { + if (grid[counter_x + (counter_y * this->width)]) + isOk = false; + } } + } while (!isOk); + + for (counter_x = x; counter_x < x + width; counter_x++) { + for (counter_y = y; counter_y < y + height; counter_y++) + grid[counter_x + (counter_y * this->width)] = true; + } return true; } diff --git a/src/Ship.cpp b/src/Ship.cpp new file mode 100644 index 0000000..14ad815 --- /dev/null +++ b/src/Ship.cpp @@ -0,0 +1,117 @@ +/* Ship.cpp -- The player's ship. + * Copyright (C) 2008 Nick Gasson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Ship.hpp" +#include "DataFile.hpp" + +extern DataFile *g_pData; + +GLuint Ship::uShipTexture = 0; + +Ship::Ship(Viewport *v) + : xpos(0), ypos(0), speedX(0), speedY(0), angle(0), viewport(v) +{ + tq.width = SHIP_TEX_WIDTH; + tq.height = SHIP_TEX_HEIGHT; +} + +void Ship::Load() +{ + OpenGL &opengl = OpenGL::GetInstance(); + + uShipTexture = opengl.LoadTextureAlpha(g_pData, "Ship.bmp"); +} + +void Ship::Display() +{ + tq.x = (int)xpos - viewport->GetXAdjust(); + tq.y = (int)ypos - viewport->GetYAdjust(); + tq.uTexture = uShipTexture; + + OpenGL::GetInstance().DrawRotate(&tq, angle); +} + +/* + * Check for collision between the ship and a polygon. + */ +bool Ship::HotSpotCollision(LineSegment &l, Point *points, int nPoints, float dx, float dy) +{ + for (int i = 0; i < nPoints; i++) { + if (CheckCollision(l, dx + points[i].x, dy + points[i].y)) + return true; + } + + return false; +} + +/* + * Checks for collision between the ship and a box. + */ +bool Ship::BoxCollision(int x, int y, int w, int h, Point *points, int nPoints) +{ + if (!viewport->PointInScreen(x, y, w, h)) + return false; + + LineSegment l1(x, y, x + w, y); + LineSegment l2(x + w, y, x + w, y + h); + LineSegment l3(x + w, y + h, x, y + h); + LineSegment l4(x, y + h, x, y); + + return HotSpotCollision(l1, points, nPoints) + || HotSpotCollision(l2, points, nPoints) + || HotSpotCollision(l3, points, nPoints) + || HotSpotCollision(l4, points, nPoints); +} + +/* + * Checks for collision between the ship and a line segment. + */ +bool Ship::CheckCollision(LineSegment &l, float dx, float dy) +{ + float xpos = this->xpos + dx; + float ypos = this->ypos + dy; + + if (!viewport->PointInScreen(xpos, ypos, SHIP_TEX_WIDTH, SHIP_TEX_HEIGHT)) + return false; + + // Get position after next move + float cX = xpos + speedX; + float cY = ypos + speedY; + + // Get displacement + float vecX = cX - xpos; + float vecY = cY - ypos; + + // Get line position + float wallX = (float)(l.p2.x - l.p1.x); + float wallY = (float)(l.p2.y - l.p1.y); + + // Work out numerator and denominator (used parametric equations) + float numT = wallX * (ypos - l.p1.y) - wallY * (xpos - l.p1.x); + float numU = vecX * (ypos - l.p1.y) - vecY * (xpos - l.p1.x); + + // Work out denominator + float denom = wallY * (cX - xpos) - wallX * (cY - ypos); + + // Work out u and t + float u = numU / denom; + float t = numT / denom; + + // Collision occured if (0 < t < 1) and (0 < u < 1) + return (t > 0.0f) && (t < 1.0f) && (u > 0.0f) && (u < 1.0f); +} + diff --git a/src/Ship.hpp b/src/Ship.hpp new file mode 100644 index 0000000..eb020c8 --- /dev/null +++ b/src/Ship.hpp @@ -0,0 +1,51 @@ +/* Ship.hpp -- The player's ship. + * Copyright (C) 2008 Nick Gasson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INC_SHIP_HPP +#define INC_SHIP_HPP + +#include "Platform.hpp" +#include "OpenGL.hpp" +#include "Geometry.hpp" +#include "Viewport.hpp" + +class Ship { +public: + Ship(Viewport *v); + + static void Load(); + + void Display(); + + bool CheckCollision(LineSegment &l, float dx=0, float dy=0); + bool HotSpotCollision(LineSegment &l, Point *points, int nPoints, float dx=0, float dy=0); + bool BoxCollision(int x, int y, int w, int h, Point *points, int nPoints); + + float xpos, ypos; + float speedX, speedY, angle; + TextureQuad tq; + +private: + static const int SHIP_TEX_WIDTH = 32; + static const int SHIP_TEX_HEIGHT = 32; + + static GLuint uShipTexture; + + Viewport *viewport; +}; + +#endif diff --git a/src/Viewport.cpp b/src/Viewport.cpp new file mode 100644 index 0000000..60ca0ca --- /dev/null +++ b/src/Viewport.cpp @@ -0,0 +1,70 @@ +/* Viewport.cpp -- The area of the screen the player can see. + * Copyright (C) 2008 Nick Gasson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "Viewport.hpp" +#include "OpenGL.hpp" +#include "ObjectGrid.hpp" + +Viewport::Viewport() + : adjustX(0), adjustY(0), levelWidth(0), levelHeight(0) +{ + screenWidth = OpenGL::GetInstance().GetWidth(); + screenHeight = OpenGL::GetInstance().GetHeight(); +} + +void Viewport::SetXAdjust(int x) +{ + adjustX = x; + if (adjustX < 0) + adjustX = 0; + else if (adjustX > levelWidth - screenWidth) + adjustX = levelWidth - screenWidth; +} + +void Viewport::SetYAdjust(int y) +{ + adjustY = y; + if (adjustY < 0) + adjustY = 0; + else if (adjustY > levelHeight - screenHeight) + adjustY = levelHeight - screenHeight; +} + +/* + * Works out whether or not a point is visible. + * xpos, ypos -> Absolute co-ordinates. + * width, height -> Size of object. + */ +bool Viewport::PointInScreen(int xpos, int ypos, int width, int height) +{ + return (xpos + width > adjustX && xpos - adjustX < screenWidth + && ypos + height > adjustY && ypos - adjustY < screenHeight); +} + +/* + * Works out whether or not an object is visible. + * xpos, ypos -> Grid co-ordinates. + * width, height -> Size of object in grid squares. + */ +bool Viewport::ObjectInScreen(int xpos, int ypos, int width, int height) +{ + return PointInScreen(xpos * ObjectGrid::OBJ_GRID_SIZE, + ypos * ObjectGrid::OBJ_GRID_SIZE, + width * ObjectGrid::OBJ_GRID_SIZE, + height * ObjectGrid::OBJ_GRID_SIZE); +} + diff --git a/src/Viewport.hpp b/src/Viewport.hpp new file mode 100644 index 0000000..54818a2 --- /dev/null +++ b/src/Viewport.hpp @@ -0,0 +1,46 @@ +/* Viewport.hpp -- The area of the screen the player can see. + * Copyright (C) 2008 Nick Gasson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INC_VIEWPORT_HPP +#define INC_VIEWPORT_HPP + +#include "Platform.hpp" + +class Viewport { +public: + Viewport(); + + int GetXAdjust() const { return adjustX; } + int GetYAdjust() const { return adjustY; } + void SetXAdjust(int x); + void SetYAdjust(int y); + + int GetLevelWidth() const { return levelWidth; } + int GetLevelHeight() const { return levelHeight; } + void SetLevelWidth(int w) { levelWidth = w; } + void SetLevelHeight(int h) { levelHeight = h; } + + bool ObjectInScreen(int xpos, int ypos, int width, int height); + bool PointInScreen(int xpos, int ypos, int width, int height); + +private: + int adjustX, adjustY; + int screenWidth, screenHeight; + int levelWidth, levelHeight; +}; + +#endif -- 2.39.5