From e3b5855edbba066da5b86046ca39c2df11d9e01b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Thu, 29 Jan 2009 23:09:51 +0000 Subject: [PATCH] Improve the way levels are generated --- src/Game.cpp | 144 +++++++++++++++++++++++++++++++------------------- src/Game.hpp | 15 ++++-- src/Input.hpp | 2 +- 3 files changed, 102 insertions(+), 59 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index 7edeafe..1acc5ba 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,6 +1,6 @@ // // Game.cpp -- Implementation of core game logic. -// Copyright (C) 2006 Nick Gasson +// Copyright (C) 2006-2009 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 @@ -31,6 +31,7 @@ #define MAX_PAD_SIZE 2 #define FUELBAR_OFFSET 68 #define GRAVITY 0.035f +const int Game::MAX_MISSILES(20); // // Constants affecting state transitions. @@ -98,7 +99,7 @@ void Game::NewGame() // Start the game level = 1; nextnewlife = 1000; - StartLevel(level); + StartLevel(); } void Game::CalculateScore(int padIndex) @@ -325,7 +326,7 @@ void Game::Process() // Fade out if (fade.Process()) { // Restart the level - StartLevel(level); + StartLevel(); opengl.SkipDisplay(); } } @@ -380,49 +381,18 @@ void Game::Process() // Increase n until it is a multiple of x and y void Game::MakeMultipleOf(int& n, int x, int y) { - cout << n << " --> "; - while (n % x > 0 || n % y > 0) ++n; - - cout << n << endl; } -void Game::StartLevel(int level) +// There are between 1 and MAX_PADS landing pads in a level +void Game::MakeLandingPads() { - cout << endl << "Start level " << level << ":" << endl; - - // Set level size - int levelWidth = 2000 + 2*Surface::SURFACE_SIZE*level; - MakeMultipleOf(levelWidth, Surface::SURFACE_SIZE, ObjectGrid::OBJ_GRID_SIZE); - - int levelHeight = 1500 + 2*Surface::SURFACE_SIZE*level; - - viewport.SetLevelWidth(levelWidth); - viewport.SetLevelHeight(levelHeight); - flGravity = GRAVITY; - - cout << " Dimensions: " << levelWidth << "x" << levelHeight << endl; - - // Create the object grid - int grid_w = viewport.GetLevelWidth() / ObjectGrid::OBJ_GRID_SIZE; - int grid_h = (viewport.GetLevelHeight() - ObjectGrid::OBJ_GRID_TOP - - MAX_SURFACE_HEIGHT - 100) / ObjectGrid::OBJ_GRID_SIZE; - objgrid.Reset(grid_w, grid_h); - - // Create background stars - nStarCount = (viewport.GetLevelWidth() * viewport.GetLevelHeight()) / 10000; - if (nStarCount > MAX_GAME_STARS) - nStarCount = MAX_GAME_STARS; - for (int i = 0; i < nStarCount; i++) { - stars[i].xpos = (int)(rand()%(viewport.GetLevelWidth()/20))*20; - stars[i].ypos = (int)(rand()%(viewport.GetLevelHeight()/20))*20; - stars[i].scale = (double)rand()/(double)RAND_MAX/8.0; - } - - // Generate landing pads pads.clear(); int nLandingPads = rand()%MAX_PADS + 1; + + cout << " Landing pads: " << nLandingPads << endl; + for (int i = 0; i < nLandingPads; i++) { int index, length; bool overlap; @@ -448,11 +418,11 @@ void Game::StartLevel(int level) pads.push_back(LandingPad(&viewport, index, length)); } +} - int surftex = rand() % Surface::NUM_SURF_TEX; - surface.Generate(surftex, pads); - - // Create the keys +// There are (level / 2) + (level % 2) keys per level +void Game::MakeKeys() +{ nKeys = (level / 2) + (level % 2); if (nKeys > MAX_KEYS) nKeys = MAX_KEYS; @@ -465,11 +435,15 @@ void Game::StartLevel(int level) objgrid.AllocFreeSpace(xpos, ypos, 1, 1); keys.push_back(Key(i < nKeysRemaining, xpos, ypos, acols[i])); } +} - // Create the asteroids - asteroidcount = level*2 + rand()%(level+3); +void Game::MakeAsteroids(int surftex) +{ + asteroidcount = 2 + level*2 + rand()%(level+3); if (asteroidcount > MAX_ASTEROIDS) asteroidcount = MAX_ASTEROIDS; + cout << " Asteroids: " << asteroidcount << endl; + for (int i = 0; i < asteroidcount; i++) { // Allocate space, check for timeout int x, y, width = rand() % (Asteroid::MAX_ASTEROID_WIDTH - 4) + 4; @@ -481,18 +455,31 @@ void Game::StartLevel(int level) // Generate the asteroid asteroids[i].ConstructAsteroid(x, y, width, surftex); } +} - // Create missiles +void Game::MakeMissiles() +{ + int missileCount = max(level - 1 + rand()%level, 0); + if (missileCount > MAX_MISSILES) + missileCount = MAX_MISSILES; + cout << " Missiles: " << missileCount << endl; + missiles.clear(); - for (int i = 0; i < 10; i++) { - missiles.push_back(Missile(&objgrid, &viewport, Missile::SIDE_RIGHT)); + for (int i = 0; i < missileCount; i++) { + Missile::Side side = + rand()%2 == 1 ? Missile::SIDE_LEFT : Missile::SIDE_RIGHT; + missiles.push_back(Missile(&objgrid, &viewport, side)); } - - // Create gateways - int gatewaycount = level/3 + rand()%level - 2; +} + +void Game::MakeGateways() +{ + int gatewaycount = max(level/3 + rand()%level - 2, 0); gateways.clear(); if (gatewaycount > MAX_GATEWAYS) gatewaycount = MAX_GATEWAYS; + cout << " Gateways: " << gatewaycount << endl; + for (int i = 0; i < gatewaycount; i++) { // Allocate space for gateway int length = rand()%(MAX_GATEWAY_LENGTH-3) + 3; @@ -511,9 +498,13 @@ void Game::StartLevel(int level) gateways.push_back(ElectricGate(&viewport, length, vertical, xpos, ypos)); } +} - // Create mines (MUST BE CREATED LAST) - int minecount = level/2 + rand()%level - 2; +void Game::MakeMines() +{ + int minecount = max(level/2 + rand()%level - 1, 0); + cout << " Mines: " << minecount << endl; + mines.clear(); if (minecount > MAX_MINES) minecount = MAX_MINES; @@ -527,7 +518,54 @@ void Game::StartLevel(int level) } mines.push_back(Mine(&objgrid, &viewport, xpos, ypos)); } +} + +void Game::StartLevel() +{ + cout << endl << "Start level " << level << ":" << endl; + + // Set level size + int levelWidth = 2000 + 2*Surface::SURFACE_SIZE*level; + MakeMultipleOf(levelWidth, Surface::SURFACE_SIZE, ObjectGrid::OBJ_GRID_SIZE); + + int levelHeight = 1500 + 2*Surface::SURFACE_SIZE*level; + + viewport.SetLevelWidth(levelWidth); + viewport.SetLevelHeight(levelHeight); + flGravity = GRAVITY; + + cout << " Dimensions: " << levelWidth << "x" << levelHeight << endl; + + // Create the object grid + int grid_w = viewport.GetLevelWidth() / ObjectGrid::OBJ_GRID_SIZE; + int grid_h = (viewport.GetLevelHeight() - ObjectGrid::OBJ_GRID_TOP + - MAX_SURFACE_HEIGHT - 100) / ObjectGrid::OBJ_GRID_SIZE; + objgrid.Reset(grid_w, grid_h); + + // Create background stars + nStarCount = (viewport.GetLevelWidth() * viewport.GetLevelHeight()) / 10000; + if (nStarCount > MAX_GAME_STARS) + nStarCount = MAX_GAME_STARS; + for (int i = 0; i < nStarCount; i++) { + stars[i].xpos = (int)(rand()%(viewport.GetLevelWidth()/20))*20; + stars[i].ypos = (int)(rand()%(viewport.GetLevelHeight()/20))*20; + stars[i].scale = (double)rand()/(double)RAND_MAX/8.0; + } + + MakeLandingPads(); + // Generate the surface + int surftex = rand() % Surface::NUM_SURF_TEX; + surface.Generate(surftex, pads); + + MakeKeys(); + MakeAsteroids(surftex); + MakeMissiles(); + MakeGateways(); + + // Create mines (MUST BE CREATED LAST) + MakeMines(); + // Set ship starting position ship.Reset(); diff --git a/src/Game.hpp b/src/Game.hpp index 2827c78..d302ca0 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -1,6 +1,6 @@ // // Game.hpp -- Definition of core game classes. -// Copyright (C) 2006 Nick Gasson +// Copyright (C) 2006-2009 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 @@ -42,9 +42,6 @@ // Different fonts to be loaded enum FontType { ftNormal, ftBig, ftScore, ftScoreName, ftLarge }; -#define MIN(a, b) (a < b ? a : b) -#define MAX(a, b) (a > b ? a : b) - class FuelMeter { public: FuelMeter(); @@ -92,13 +89,20 @@ public: void Process(); void Display(); void NewGame(); - void StartLevel(int nLevel); + void StartLevel(); private: static const float TURN_ANGLE, DEATH_SPIN_RATE; static const int FUEL_BASE, FUEL_PER_LEVEL; static const int SCORE_PAD_SIZE, SCORE_LEVEL, SCORE_FUEL_DIV; static const int SCORE_Y, DEATH_TIMEOUT; + + void MakeLandingPads(); + void MakeKeys(); + void MakeAsteroids(int surftex); + void MakeMissiles(); + void MakeGateways(); + void MakeMines(); void ExplodeShip(); void EnterDeathWait(int timeout = DEATH_TIMEOUT); @@ -170,6 +174,7 @@ private: MineList mines; // Missiles + static const int MAX_MISSILES; typedef vector MissileList; typedef MissileList::iterator MissileListIt; MissileList missiles; diff --git a/src/Input.hpp b/src/Input.hpp index 299a78c..c2afa1b 100644 --- a/src/Input.hpp +++ b/src/Input.hpp @@ -48,7 +48,7 @@ private: ~Input(); static const int NUM_ACTIONS = 10; - static const int RESET_TIMEOUT = 10; // Frames between key presses + static const int RESET_TIMEOUT = 7; // Frames between key presses SDL_Joystick* joystick; -- 2.39.2