int GameLevelScript::RespawnPlayer( CLuaVirtualMachine& vm )
{
	lua_State* state = static_cast<lua_State*>( vm );
	const std::string respawnId = lua_tostring( state, -1 );

	const int currentStateId = GameState::GetStateID();
	if( currentStateId == GameState::k_state_gameplay )
	{
		GS_GamePlay* gameplay = static_cast<GS_GamePlay*>( GameState::GetCurrentState() );
		if( gameplay )
		{
			GameLevel* gamelevel = gameplay->GetGameLevel();
			if( gamelevel )
			{
				Player* player = gamelevel->GetPlayer();
				if( player )
				{
					player->Respawn( respawnId );
				}
			}
		}
	}

	return 0;
}
예제 #2
0
void Submarine::draw(GameLevel& context) const {
  if(armor == 0 || (extraLives >= 0 && context.frameCount() / 3 % 2 == 0)) {
    context.core.drawBitmap(fieldX() - 1, fieldY() - 2, bitmapSubmarine, 2);
    if(context.frameCount() % ECHO_CYCLE > 30) {  // sustain: 30 frames
      context.core.drawPixel(fieldX() + 6, fieldY() - 1, 1);
    }
  }
  //context.getArduboy().drawRect(x, y, W, H, 0);
}
예제 #3
0
void Generator::draw(GameLevel& context) const {
  if(dispTimer > 0 && context.frameCount() / 5 % 2 == 0) {
    char text[12];
    sprintf(text, "Score %05d", context.getScore());
    context.core.setCursor(SCREEN_WIDTH / 2 - 6 * 11 / 2, 0);
    context.core.print(text);
    sprintf(text, "ZONE%3d", zone);
    context.core.setCursor(SCREEN_WIDTH / 2 - 6 * 7 / 2, 10);
    context.core.print(text);
  }
}
GameLevel* Game::CreateGameLevel( const int modeID, const int levelID )
{
	Physics* physics = Physics::GetInstance();
	physics->Init();

	GameLevel* gameLevel = new GameLevel( modeID, levelID );
	gameLevel->Init();

	physics->FreeInstance();

	return gameLevel;
}
예제 #5
0
void Game::InitGame()
{
	winPositions[0] = (GLfloat)this->Width;
	winPositions[1] = (GLfloat)this->Width;
	Text = new TextRenderer(this->Width, this->Height);
	Text->Load("QuickJerk/DUNEBUG.ttf", 20);
	SoundEngine->play2D("audio/windy.mp3", GL_TRUE);
	ResourceMaster::LoadShader("SpriteShader.vert", "SpriteShader.frag", nullptr, "sprite");
	ResourceMaster::LoadShader("ParticleShader.vert", "ParticleShader.frag", nullptr, "particle");
	ResourceMaster::LoadShader("PostProcess.vert", "PostProcess.frag", nullptr, "postproc");
	glm::mat4 projection = glm::ortho(0.0f,
		static_cast<GLfloat>(this->Width), static_cast<GLfloat>(this->Height), 0.0f, -1.0f, 1.0f);
	ResourceMaster::GetShader("sprite").Use().SetInteger("image", 0);
	ResourceMaster::GetShader("sprite").SetMatrix4("projection", projection);
	ResourceMaster::GetShader("particle").Use().SetInteger("image", 0);
	ResourceMaster::GetShader("particle").SetMatrix4("projection", projection);
	Renderer = new SpriteRenderer(ResourceMaster::GetShader("sprite"));
	ResourceMaster::LoadTexture("Sprites/particle.png", GL_TRUE, "particle");
	ResourceMaster::LoadTexture("Sprites/SquidPaddle.png", GL_TRUE, "squidPaddle", 5);
	ResourceMaster::LoadTexture("Sprites/DeadSquid.png", GL_TRUE, "deadSquid", 12);
	ResourceMaster::LoadTexture("Sprites/background.png", GL_TRUE, "background");
	ResourceMaster::LoadTexture("Sprites/Blocks/plain.png", GL_FALSE, "plain");
	ResourceMaster::LoadTexture("Sprites/Blocks/indestructible.png", GL_FALSE, "indestructible");
	ResourceMaster::LoadTexture("Sprites/Blocks/chaos.png", GL_FALSE, "chaos");
	ResourceMaster::LoadTexture("Sprites/Blocks/dizzy.png", GL_FALSE, "dizzy");
	ResourceMaster::LoadTexture("Sprites/Blocks/invert.png", GL_FALSE, "invert");
	ResourceMaster::LoadTexture("Sprites/Blocks/magnet.png", GL_FALSE, "magnet");
	ResourceMaster::LoadTexture("Sprites/EyeBraun/globe.png", GL_TRUE, "globe");
	ResourceMaster::LoadTexture("Sprites/EyeBraun/veins.png", GL_TRUE, "veins");
	ResourceMaster::LoadTexture("Sprites/EyeBraun/iris.png", GL_TRUE, "iris");
	ResourceMaster::LoadTexture("Sprites/EyeBraun/pupil.png", GL_TRUE, "pupil");
	ResourceMaster::LoadTexture("Sprites/Blocks/speed.png", GL_TRUE, "speed");
	ResourceMaster::LoadTexture("Sprites/Blocks/slow.png", GL_TRUE, "slow");
	ResourceMaster::LoadTexture("Sprites/Blocks/extend.png", GL_TRUE, "extend");
	ResourceMaster::LoadTexture("Sprites/Blocks/baby.png", GL_TRUE, "baby", 9);
	ResourceMaster::LoadTexture("Sprites/Blocks/death.png", GL_TRUE, "death");
	Particles = new ParticleGenerator(ResourceMaster::GetShader("particle"), 
		ResourceMaster::GetTexture("particle"), 500);
	Effects = new PostProcessor(ResourceMaster::GetShader("postproc"), this->Width, this->Height);
	glm::vec2 playerPos = glm::vec2(
		this->Width / 2 - PLAYER_SIZE.x / 2,
		this->Height - PLAYER_SIZE.y
		);
	Player = new GameObject(playerPos, PLAYER_SIZE, ResourceMaster::GetTexture("squidPaddle"));
	glm::vec2 ballPos = playerPos + glm::vec2(PLAYER_SIZE.x / 2 - BALL_RADIUS, -BALL_RADIUS * 2);
	GameBall = new Ball(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY,
		ResourceMaster::GetTexture("globe"));
	GameLevel one;
	one.Load("Levels/LevelOne.txt", this->Width, (GLuint)(this->Height * 0.5f));
	this->Levels.push_back(one);
	this->Level = 0;
}
예제 #6
0
void Submarine::onHit(GameLevel& context) {
  if(armor <= 0) {
    if(extraLives >= 0) {
      context.spawnParticle(fieldX() - 2, fieldY() - 4, PARTICLE_EXPLOSION);
      context.core.tone(185, 250);
    }
    --extraLives;
    if(extraLives < 0) {
      context.setGameover();
      // ToDo: add gameover sfx
      inactivate();
    }
    armor = ARMOR_FRAMES;
  }
}
예제 #7
0
void SmallEnemy::onHit(GameLevel& context) {
  context.addScore(1);
  if(x < SCREEN_WIDTH + 20) { // near
    context.spawnParticle(round(x) - 5, round(y) - 4, PARTICLE_EXPLOSION);
    context.core.tone(880, 62);
  }
  // platoon elimination
  if(context.platoons.checkBonus(getPlatoon(), true)) {
    if(x < SCREEN_WIDTH + 20) { // near
      context.spawnParticle(round(x) - 2, round(y) - 2, PARTICLE_TEN_POINT);
    }
    context.addScore(10);
  }
  inactivate();
}
예제 #8
0
void Platoons::spawn(GameLevel& context) {
  const byte INTERVALS[] = {10, 16, 16};
  for(byte i = 0; i < PLATOON_MAX; ++i) {
    if(!inUse(i)) { continue; }
    if(
      timers[i] % INTERVALS[types[i]] == 0 &&
      timers[i] < PLATOON_CONSISTS * INTERVALS[types[i]]  // limitation PLATOON_CONSISTS
    ) {
      // type
      const byte isOdd = timers[i] / INTERVALS[types[i]] % 2 == 1; // 0123 -> 1234
      byte spawnType;
      if(types[i] == PLATOON_ZIG_FILE) {
        spawnType = isOdd ? SENEMY_ZIG_FIRE : SENEMY_ZIG_NOFIRE;
      }
      else {
        spawnType = isOdd ? SENEMY_TRI_FIRE : SENEMY_TRI_NOFIRE;
      }
      // y
      char y = spawnYs[i];
      if(types[i] == PLATOON_TRI_SHOAL) {
        y += random(20) - 10;
      }
      // spawn
      if(context.spawnSmallEnemy(y, (i << 4) | spawnType)) {
        status[i] = 0;  // reset platoon
      }
    }
    if(timers[i] < 0xff) {
      ++timers[i];
    }
  }
}
예제 #9
0
파일: Game.cpp 프로젝트: Itanq/openglDemo
// 初始化游戏
void Game::Init()
{
    // 加载相关着色器
    ResourceManager::LoadShader("shaders/spriteVertexShader.glsl", "shaders/spriteFragmentShader.glsl", nullptr, "sprite");
    ResourceManager::LoadShader("shaders/particleVertexShader.glsl", "shaders/particleFragmentShader.glsl", nullptr, "particle");
    ResourceManager::LoadShader("shaders/vertexShader.glsl", "shaders/fragmentShader.glsl", nullptr, "postprocessing");
	ResourceManager::LoadShader("shaders/textVertexShader.glsl", "shaders/textFragmentShader.glsl", nullptr, "text");
   
    // 设置相关着色器
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(this->Width), static_cast<GLfloat>(this->Height), 0.0f, -1.0f, 1.0f);
    ResourceManager::GetShader("sprite").Use().SetInteger("sprite", 0);
    ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
    ResourceManager::GetShader("particle").Use().SetInteger("sprite", 0);
    ResourceManager::GetShader("particle").SetMatrix4("projection", projection);
	
    // 加载相关纹理
    ResourceManager::LoadTexture("textures/background.jpg", GL_TRUE, "background");
    ResourceManager::LoadTexture("textures/awesomeface.png", GL_TRUE, "face");
    ResourceManager::LoadTexture("textures/block.png", GL_TRUE, "block");
    ResourceManager::LoadTexture("textures/block_solid.png", GL_TRUE, "block_solid");
    ResourceManager::LoadTexture("textures/paddle.png", GL_TRUE, "paddle");
    ResourceManager::LoadTexture("textures/particle.png", GL_TRUE, "particle");
    ResourceManager::LoadTexture("textures/powerup_speed.png", GL_TRUE, "powerup_speed");
    ResourceManager::LoadTexture("textures/powerup_sticky.png", GL_TRUE, "powerup_sticky");
    ResourceManager::LoadTexture("textures/powerup_increase.png", GL_TRUE, "powerup_increase");
    ResourceManager::LoadTexture("textures/powerup_confuse.png", GL_TRUE, "powerup_confuse");
    ResourceManager::LoadTexture("textures/powerup_chaos.png", GL_TRUE, "powerup_chaos");
    ResourceManager::LoadTexture("textures/powerup_passthrough.png", GL_TRUE, "powerup_passthrough");

    // 根据着色器设置相应的渲染
    Renderer = new SpriteRenderer(ResourceManager::GetShader("sprite"));
    Particles = new ParticleGenerator(ResourceManager::GetShader("particle"), ResourceManager::GetTexture("particle"), 500);
    Effects = new PostProcessor(ResourceManager::GetShader("postprocessing"), this->Width, this->Height);
    Text = new TextRenderer(ResourceManager::GetShader("text"), this->Width, this->Height);
    Text->Load("fonts/arial.ttf", 24);

    // 加载游戏的不同难度
    GameLevel one; one.Load("levels/one.lvl", this->Width, this->Height * 0.5);
    GameLevel two; two.Load("levels/two.lvl", this->Width, this->Height * 0.5);
    GameLevel three; three.Load("levels/three.lvl", this->Width, this->Height * 0.5);
    GameLevel four; four.Load("levels/four.lvl", this->Width, this->Height * 0.5);
    this->Levels.push_back(one);
    this->Levels.push_back(two);
    this->Levels.push_back(three);
    this->Levels.push_back(four);
    this->Level = 0;

    // 设置游戏对象
    glm::vec2 playerPos = glm::vec2(this->Width / 2 - PLAYER_SIZE.x / 2, this->Height - PLAYER_SIZE.y);
    Player = new GameObject(playerPos, PLAYER_SIZE, ResourceManager::GetTexture("paddle"));
    glm::vec2 ballPos = playerPos + glm::vec2(PLAYER_SIZE.x / 2 - BALL_RADIUS, -BALL_RADIUS * 2);
    Ball = new BallObject(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY, ResourceManager::GetTexture("face"));

    // 背景音乐
    BackgroudMusic->play2D("audio/breakout.mp3", GL_TRUE);
}
예제 #10
0
파일: Game.cpp 프로젝트: abhi360/BasicGame
void Game::Init()
{
	// Load shaders
	ResourceManager::LoadShader("src/Shader/shader_vertex.vert", "src/Shader/shader_fragment.frag", nullptr, "sprite");
	ResourceManager::LoadShader("src/Shader/particle.vert", "src/Shader/particle.frag", nullptr, "particle");
	ResourceManager::LoadShader("src/Shader/post_processing.vs", "src/Shader/post_processing.frag", nullptr, "postprocessing");
	// Configure shaders
	glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(this->Width),
		static_cast<GLfloat>(this->Height), 0.0f, -1.0f, 1.0f);
	ResourceManager::GetShader("sprite").Use().SetInteger("image", 0);
	ResourceManager::GetShader("sprite").SetMatrix4("projection", projection);
	ResourceManager::GetShader("particle").Use().SetInteger("sprite", 0);
	ResourceManager::GetShader("particle").SetMatrix4("projection", projection);
	// Load textures
	ResourceManager::LoadTexture("src/Textures/background.jpg", GL_FALSE, "background");
	ResourceManager::LoadTexture("src/Textures/awesomeface.png", GL_TRUE, "face");
	ResourceManager::LoadTexture("src/Textures/block.png", GL_FALSE, "block");
	ResourceManager::LoadTexture("src/Textures/block_solid.png", GL_FALSE, "block_solid");
	ResourceManager::LoadTexture("src/Textures/paddle.png", GL_TRUE , "paddle");
	ResourceManager::LoadTexture("src/Textures/particle.png", GL_TRUE, "particle");
	ResourceManager::LoadTexture("src/Textures/powerup_speed.png", GL_TRUE, "powerup_speed");
	ResourceManager::LoadTexture("src/Textures/powerup_sticky.png", GL_TRUE, "powerup_sticky");
	ResourceManager::LoadTexture("src/Textures/powerup_increase.png", GL_TRUE, "powerup_increase");
	ResourceManager::LoadTexture("src/Textures/powerup_confuse.png", GL_TRUE, "powerup_confuse");
	ResourceManager::LoadTexture("src/Textures/powerup_chaos.png", GL_TRUE, "powerup_chaos");
	ResourceManager::LoadTexture("src/Textures/powerup_passthrough.png", GL_TRUE, "powerup_passthrough");

	Renderer = new SpriteRenderer(ResourceManager::GetShader("sprite"));
	Particles = new ParticleGenerator(ResourceManager::GetShader("particle"), ResourceManager::GetTexture("particle"), 500);
	Effects = new PostProcessor(ResourceManager::GetShader("postprocessing"), this->Width, this->Height);
	Text = new TextRenderer(this->Width, this->Height);
	Text->Load("src/Fonts/OCRAEXT.TTF", 24);
	// Load levels
	GameLevel one; one.Load("src/Level/one.lvl", this->Width, this->Height * 0.5);
	GameLevel two; two.Load("src/Level/two.lvl", this->Width, this->Height * 0.5);
	GameLevel three; three.Load("src/Level/three.lvl", this->Width, this->Height * 0.5);
	GameLevel four; four.Load("src/Level/four.lvl", this->Width, this->Height * 0.5);
	this->Levels.push_back(one);
	this->Levels.push_back(two);
	this->Levels.push_back(three);
	this->Levels.push_back(four);
	this->Level = 0;
	// Configure game objects
	glm::vec2 playerPos = glm::vec2(this->Width / 2 - PLAYER_SIZE.x / 2, this->Height - PLAYER_SIZE.y);
	Player = new GameObject(playerPos, PLAYER_SIZE, ResourceManager::GetTexture("paddle"));
	glm::vec2 ballPos = playerPos + glm::vec2(PLAYER_SIZE.x / 2 - BALL_RADIUS, -BALL_RADIUS * 2);
	Ball = new BallObject(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY,
		ResourceManager::GetTexture("face"));

	//Effects->Shake = GL_TRUE;
	//Effects->Confuse = GL_TRUE;
	//Effects->Chaos = GL_TRUE;
	SoundEngine->play2D("src/Audio/breakout.mp3", GL_TRUE);

}
예제 #11
0
void Submarine::move(GameLevel& context) {
  if(context.isGameover()) { return; }
  
  // control
  static const int SPD = 1 << 7;
  static const int R2  = 90;  // 0.5/sqrt(2) / (1/256)
  if(context.core.pressed(BTN_U) && context.core.pressed(BTN_L)) {
    x -= R2;
    y -= R2;
  }
  else if(context.core.pressed(BTN_U) && context.core.pressed(BTN_R)) {
    x += R2;
    y -= R2;
  }
  else if(context.core.pressed(BTN_D) && context.core.pressed(BTN_L)) {
    x -= R2;
    y += R2;
  }
  else if(context.core.pressed(BTN_D) && context.core.pressed(BTN_R)) {
    x += R2;
    y += R2;
  }
  else if(context.core.pressed(BTN_U)) {
    y -= SPD;
  }
  else if(context.core.pressed(BTN_L)) {
    x -= SPD;
  }
  else if(context.core.pressed(BTN_R)) {
    x += SPD;
  }
  else if(context.core.pressed(BTN_D)) {
    y += SPD;
  }

  // clamping into field
  static const fixed MARGIN = 6;
  x = Clamp(x, 0, (SCREEN_WIDTH - MARGIN) << 8);
  y = Clamp(y, (MARGIN - H) << 8, (SCREEN_HEIGHT - MARGIN) << 8);

  // launching torpedo
  if(extraLives >= 0 && (context.core.pushed(BTN_A) || context.core.pushed(BTN_B))) {
    context.launchTorpedo((int)fieldX() + 10, fieldY() + 1);
  }

  //firing auto shot
#ifdef LOW_FLASH_MEMORY
  if(context.frameCount() % 5 == 0) {
    context.fireAutoShot(fieldX() + 3, fieldY() - 3);
  }
#else
  if(context.lookForEnemy() && context.frameCount() % 5 == 0) {
    context.fireAutoShot(fieldX() + 3, fieldY() - 3);
  }
#endif

  // updating armor timer
  if(armor > 0) { --armor; }
}
예제 #12
0
void BigEnemy::onHit(GameLevel& context) {
  // add score
  context.addScore(10);
  if(x > SCREEN_WIDTH) {  // far bonus
    context.addScore((x - SCREEN_WIDTH) * 10 / (FIELD_WIDTH - SCREEN_WIDTH));
  }
  // near
  if(x < SCREEN_WIDTH + 20) {
    context.core.tone(1047, 250);
    context.spawnParticle(x + random(-2,  8), y + random(-4, 4), PARTICLE_EXPLOSION);
    context.spawnParticle(x + random( 8, 18), y + random(-4, 4), PARTICLE_EXPLOSION);
#ifndef LOW_FLASH_MEMORY
    context.removeAllBullets();
    context.core.setQuake();
#endif
  }
  // reset
  inactivate();
}
예제 #13
0
void Echo::reset(GameLevel& context, const byte subX) {
  if(context.frameCount() % ECHO_CYCLE == 0) {
    for(byte i = 0; i < ECHO_VERT_RESO; ++i) {
      intensities[i] = 0;
    }
    acceptFlag = true;
  }
  else {
    acceptFlag = false;
  }
  submarineX = subX;
}
예제 #14
0
void Echo::draw(GameLevel& context) const {
  if(
    context.frameCount() / 3 % 2 == 0 ||  // tearing
    context.frameCount() % ECHO_CYCLE < ECHO_CYCLE / 2  // sustain: 30 frames
  ) {
    return;
  }
  for(byte i = 0; i < ECHO_VERT_RESO; ++i) {
    for(byte j = 0; j < intensities[i]; ++j) {
      context.core.fillRect(SCREEN_WIDTH - (j - 1) * ECHO_GRID_SIZE, i * ECHO_GRID_SIZE, ECHO_GRID_SIZE - 1, ECHO_GRID_SIZE - 1, 1);
    }
  }
}
예제 #15
0
void Bullet::draw(GameLevel& context) const {
  // ToDo: async animation (if there are enough memories)
  const byte frame = context.frameCount() / 3 % 2;
  
  if(type % 2 == 0) {
    const byte* bitmaps[] = {bitmapMbullet0, bitmapMbullet1};
    context.core.drawBitmap(fieldX() - bitmapMbullet0[0]/2, fieldY() - bitmapMbullet0[1]/2, bitmaps[frame], 2);
  }
  else {
    const byte* bitmaps[] = {bitmapSbullet0, bitmapSbullet1};
    context.core.drawBitmap(fieldX() - bitmapSbullet0[0]/2, fieldY() - bitmapSbullet0[1]/2, bitmaps[frame], 2);
  }
  //arduboy.drawPixel(x, y, 0);
}
예제 #16
0
void BigEnemy::move(GameLevel& context) {
  // moving
  if(grazed() && x > SCREEN_WIDTH - 5) {
    x += -3; // submarine found
  }
  else if(timer % 5 == 0) { // -0.2
    --x;
  }

  // frame out
  if(x + bitmapCruEnemy0[0] < 0) {
    inactivate();
  }

  // setting sonar reaction
  context.echo.add(x, y, y+H);

  // firing bullet
  if(x < SCREEN_WIDTH - W / 2) {
    if(!onScreen()) {
      timer = 0;  // in order to sync fire cycle
      state |= ON_SCREEN_MASK;
    }
    const byte d = context.difficulty();
    if(timer == 0 || (d >= 60 && timer == 40)) {  // freq up when 60 and over
      const char bulletY     = y + bitmapCruEnemy0[1] / 2;
      const char bulletSpeed = (d >= 80) ? BULLET_TYPE2_SPD : BULLET_TYPE0_SPD;
      const char bulletType  = (d >= 80) ? 2 : 0;
      context.fireBullet(x, bulletY, context.getFutureSubmarineAngle(x, bulletY, bulletSpeed), bulletType);
    }
  }

  // updating timer
  static const byte PERIOD = 150;
  timer = (timer + 1) % PERIOD;
}
예제 #17
0
void SmallEnemy::move(GameLevel& context) {
  const byte period = (getType() == 0) ? ZIG_PERIOD : TRI_PERIOD;

  switch(getType()) {
    // zigzag
    case 0: {
      // moving
      // x -= 1.5, y -= 0.5
      if(timer % 2 == 0) {
        x -= 2;
        y += (timer / (ZIG_PERIOD / 4) % 2 == 0) ? 1 : -1;
      }
      else {
        --x;
      }
      
      // firing bullet
      const byte d = context.difficulty();
      const byte typeCond = canFire() || 
        (d >= 70 && d < 80) || d >= 100;  // [70,80) or 100
      if(
        timer == 80 && typeCond &&    // time / type
        x < SCREEN_WIDTH - W / 2 &&   // position
        d >= 20                       // dont fire less than 20
      ) {
        const byte  bulletType = (d >= 80) ? 3 : 1;  // rapid when 80 and over
        const float subAngle   = context.getSubmarineAngle(x, y);
        context.fireBullet(x, y, subAngle, bulletType);
        // 3way
        if((d >= 50 && d < 70) || d >= 90) {
          context.fireBullet(x, y, subAngle - radians(10), 1);
          context.fireBullet(x, y, subAngle + radians(10), 1);
        }
      }
    } break;

    // triangle
    default: {
      // moving
      if(timer % 6 == 0) { --x; }
      const int half = period / 2;
      int tmp = half - timer % half;
      tmp = tmp*tmp / (half*half/4) - 1;
      if(tmp < 0) { tmp = 0; }
      x -= tmp;
      
      // firing bullet
      const bool timeCond = timer == 64 || 
        (context.difficulty() >= 25 && timer == 32) || 
        (context.difficulty() >= 75 && timer == 96);
      if(
        timeCond && canFire() &&                    // time / type
        x < SCREEN_WIDTH && x > SCREEN_WIDTH / 2 && // position
        context.difficulty() >= 20                  // difficulty
      ) {
        context.fireBullet(x, y, context.getSubmarineAngle(x, y), 1);
      }
    } break;
  }

  // frame out
  if(x + 12 < 0) {
    context.platoons.checkBonus(getPlatoon(), false);
    inactivate();
  }

  // setting sonar reaction
  context.echo.add(x, y, y+H);

  // updating timer
  timer = (timer + 1) % period;
}
예제 #18
0
void Generator::spawn(GameLevel& context) {
#ifdef DEBUG
  if(context.core.pressed(BTN_B)) {
    if(context.core.pushed(BTN_U)) { difficulty += 10; }
    if(context.core.pushed(BTN_D)) { difficulty -= 10; }
  }
#endif

  if(dispTimer  > 0) { --dispTimer; }
  if(delayTimer > 0) { --delayTimer; return; }  // if delaying, skip generating step
  
  const byte* waves[] = { // generating scripts
#ifdef DEBUG
    waveTest,
#else 
    waveEmpty, // 0
#endif
    waveBeginner0, waveBeginner1, waveRandomLines, waveZigTop, waveZigBottom,  // easy 1-5
    waveTriTri, waveSandwich, waveCatapult, waveSuperPlatoon,   // normal 6-9
    waveBigWall, waveJamming, waveCamouflage0, waveCamouflage1, waveArrows  // hard 10-14
  };
  static const byte DIFFICULTY_GROUP[] = {5, 4, 5};
  //static const byte WAVE_PATTERN_MAX = 15;
  byte inst;  // current instruction (or operand)

  inst = pgm_read_byte(waves[waveIndex] + progCount); // fetch
  while(inst != INST_END_WAVE && delayTimer <= 0) {
    // spawn
    if((inst & INST_SPAWN_MASK) != 0) {
      const byte type = inst & INST_TYPE_MASK;
      
      // get next operand
      ++progCount;
      inst = pgm_read_byte(waves[waveIndex] + progCount);
      const byte rand = inst & INST_RAND_MASK;
      if(rand == INST_RAND_ERROR) { break; }  // invalid operand
      byte y = inst & INST_Y_MASK;
      if     (rand == INST_RAND_WIDE  ) { y =  random(4, 57);  }
      else if(rand == INST_RAND_NARROW) { y += random(10) - 5; }
      
      switch(type) {
        case SPAWN_BIG:        context.spawnBigEnemy  (y);                      break;
        case SPAWN_ZIG_SINGLE: context.spawnSmallEnemy(y-5, SENEMY_ZIG_FIRE  ); break;
        case SPAWN_ZIG_FILE:   context.platoons.set   (y-5, PLATOON_ZIG_FILE ); break;
        case SPAWN_TRI_SINGLE: context.spawnSmallEnemy(y  , SENEMY_TRI_FIRE  ); break;
        case SPAWN_TRI_LINE:   context.platoons.set   (y  , PLATOON_TRI_LINE ); break;
        case SPAWN_TRI_SHOAL:  context.platoons.set   (y  , PLATOON_TRI_SHOAL); break;
        default: break;
      }
    }
    // delay
    else {
      delayTimer = inst;
    }
    
    // get next instruction
    ++progCount;
    inst = pgm_read_byte(waves[waveIndex] + progCount);
  }

  // next wave
  static const byte ZONE_DISP_FRAMES = 90;
  static const byte DIFFICULTY_INCR  = 20;
  static const byte DIFFICULTY_DECR  = 10;
  if(inst == INST_END_WAVE && delayTimer <= 0) {
    ++waveCount;
    progCount = 0;
    
    // difficulty limit
    byte randNum;
    byte randMin = 1; // except zero
    if(getDifficulty() < 10) {
      randNum = DIFFICULTY_GROUP[0];
    }
    else if(getDifficulty() < 50) {
      randNum = DIFFICULTY_GROUP[0] + DIFFICULTY_GROUP[1];
    }
    else if(getDifficulty() < 70) {
      randNum = DIFFICULTY_GROUP[0] + DIFFICULTY_GROUP[1] + DIFFICULTY_GROUP[2];
    }
    else{
      randNum =  DIFFICULTY_GROUP[1] + DIFFICULTY_GROUP[2];
      randMin += DIFFICULTY_GROUP[0];
    }
    waveIndex = random(randNum) + randMin;
    
    // difficulty up
    if(difficulty < DIFFICULTY_CAP + DIFFICULTY_DECR) {
      difficulty += DIFFICULTY_INCR / WAVES_IN_ZONE;
    }
    
    // next zone
    if(waveCount >= WAVES_IN_ZONE) {
      waveCount = 0;
      dispTimer = ZONE_DISP_FRAMES;  // disp zone and score
      ++zone;
      // difficulty down
      if(difficulty < DIFFICULTY_CAP + DIFFICULTY_DECR && zone > 1) {
        difficulty -= DIFFICULTY_DECR;
      }
    }
  }
}