Logo Search packages:      
Sourcecode: val-and-rick version File versions  Download package

field.d

/*
 * $Id: field.d,v 1.1.1.1 2005/03/13 16:15:04 kenta Exp $
 *
 * Copyright 2005 Kenta Cho. Some rights reserved.
 */
module abagames.vr.field;

private import opengl;
private import std.math;
private import abagames.util.vector;
private import abagames.util.rand;
private import abagames.util.sdl.texture;
private import abagames.vr.screen;
private import abagames.vr.shape;
private import abagames.vr.stagemanager;
private import abagames.vr.ship;

/**
 * Game field.
 */
00021 public class Field {
 public:
  static const int BLOCK_SIZE_X = 20;
  static const int BLOCK_SIZE_Y = 64;
 private:
  static const float TEXTURE_SIZE = 1;
  static const int NEXT_BLOCK_AREA_SIZE = 16;
  static const float SIDEWALL_X1 = 18;
  static const float SIDEWALL_X2 = 9.3f;
  static const float SIDEWALL_Y = 15;
  StageManager stageManager;
  Ship ship;
  Rand rand;
  Texture spaceTexture;
  BitmapShape[] groundShape;
  Vector _size, _outerSize;
  const int SCREEN_BLOCK_SIZE_X = 20;
  const int SCREEN_BLOCK_SIZE_Y = 24;
  const float BLOCK_WIDTH = 1;
  int[BLOCK_SIZE_Y][BLOCK_SIZE_X] block;
  int[BLOCK_SIZE_Y / 4][BLOCK_SIZE_X / 4] spacePattern;
  int nextBlockY;
  float screenY, spaceY, blockCreateCnt;
  float _lastScrollY;
  Vector screenPos;
  Vector[] panelPos;
  int panelPosNum;

  public this() {
    rand = new Rand();
    _size = new Vector(SCREEN_BLOCK_SIZE_X / 2 * 0.9f, SCREEN_BLOCK_SIZE_Y / 2 * 0.86f);
    _outerSize = new Vector(SCREEN_BLOCK_SIZE_X / 2, SCREEN_BLOCK_SIZE_Y / 2);
    spaceTexture = new Texture("all.bmp", 0, 384, 3, 1, 128, 128);
    groundShape = new BitmapShape[20];
    for (int i = 0; i < groundShape.length; i++) {
      groundShape[i] = new BitmapShape(BitmapShape.ground, i);
    }
    screenPos = new Vector;
    setRandSeed(3);
    for (int i = 0; i < 5; i++)
      spacePattern[rand.nextInt(BLOCK_SIZE_X / 4)][rand.nextInt(BLOCK_SIZE_Y / 4)] = 1;
    for (int i = 0; i < 2; i++)
      spacePattern[rand.nextInt(BLOCK_SIZE_X / 4)][rand.nextInt(BLOCK_SIZE_Y / 4)] = 2;
    panelPos = new Vector[SCREEN_BLOCK_SIZE_X * NEXT_BLOCK_AREA_SIZE];
    foreach (inout Vector pp; panelPos)
      pp = new Vector;
  }

  public void setStageManager(StageManager sm) {
    stageManager = sm;
  }

  public void setShip(Ship sp) {
    ship = sp;
  }

  public void setRandSeed(long s) {
    rand.setSeed(s);
  }

  public void start() {
    _lastScrollY = 0;
    nextBlockY = 0;
    screenY = spaceY = NEXT_BLOCK_AREA_SIZE;
    blockCreateCnt = 0;
    for (int y = 0; y < BLOCK_SIZE_Y; y++)
      for (int x = 0; x < BLOCK_SIZE_X; x++)
        block[x][y] = -1;
  }

  public void scroll(float my, bool isDemo = false) {
    _lastScrollY = my;
    screenY -= my;
    if (screenY < 0)
      screenY += BLOCK_SIZE_Y;
    spaceY -= my * 0.025f;
    if (spaceY < 0)
      spaceY += BLOCK_SIZE_Y / 4;
    blockCreateCnt -= my;
    if (blockCreateCnt < 0) {
      createBlocks();
      if (!isDemo) {
        stageManager.addBatteries(panelPos, panelPosNum);
        if (ship.purserReady) {
          int lby = nextBlockY + NEXT_BLOCK_AREA_SIZE - 1;
          if (lby >= BLOCK_SIZE_Y)
            lby -= BLOCK_SIZE_Y;
          Vector sp = convertToScreenPos(0, lby);
          ship.setPurser(0, sp.y);
        }
      }
      gotoNextBlockArea();
    }
  }

  public int getBlock(Vector p) {
    return getBlock(p.x, p.y);
  }

  public int getBlock(float x, float y) {
    y -= screenY - cast(int) screenY;
    int bx, by;
    bx = cast(int) ((x + BLOCK_WIDTH * SCREEN_BLOCK_SIZE_X / 2) / BLOCK_WIDTH);
    by = cast(int)screenY + cast(int) ((-y + BLOCK_WIDTH * SCREEN_BLOCK_SIZE_Y / 2) / BLOCK_WIDTH);
    if (bx < 0 || bx >= BLOCK_SIZE_X)
      return 0;
    if (by < 0)
      by += BLOCK_SIZE_Y;
    else if (by >= BLOCK_SIZE_Y)
      by -= BLOCK_SIZE_Y;
    return block[bx][by];
  }

  public void setRuin(int bx, int by) {
    block[bx][by] = 10;
  }

  public Vector convertToScreenPos(int bx, int y) {
    float oy = screenY - cast(int) screenY;
    int by = y - cast(int) screenY;
    if (by <= -BLOCK_SIZE_Y)
      by += BLOCK_SIZE_Y;
    if (by > 0)
      by -= BLOCK_SIZE_Y;
    screenPos.x = bx * BLOCK_WIDTH - BLOCK_WIDTH * SCREEN_BLOCK_SIZE_X / 2 + BLOCK_WIDTH / 2;
    screenPos.y = by * -BLOCK_WIDTH + BLOCK_WIDTH * SCREEN_BLOCK_SIZE_Y / 2 + oy - BLOCK_WIDTH / 2;
    return screenPos;
  }

  public void draw() {
    Screen.setColor(1, 1, 1);
    int by = cast(int) spaceY;
    float oy = (spaceY - by) * 4;
    float sx;
    float sy = BLOCK_WIDTH * SCREEN_BLOCK_SIZE_Y / 2 + oy;
    glDisable(GL_BLEND);
    for (int y = 0; y < SCREEN_BLOCK_SIZE_Y / 4 + 1; y++) {
      if (by >= BLOCK_SIZE_Y / 4)
        by -= BLOCK_SIZE_Y / 4;
      sx = -BLOCK_WIDTH * SCREEN_BLOCK_SIZE_X / 2;
      for (int bx = 0; bx < SCREEN_BLOCK_SIZE_X / 4; bx++) {
        spaceTexture.bind(spacePattern[bx][by]);
        glBegin(GL_TRIANGLE_FAN);
        glTexCoord2f(0, 0);
        glVertex3f(sx, sy, 0);
        glTexCoord2f(TEXTURE_SIZE, 0);
        glVertex3f(sx + BLOCK_WIDTH * 4, sy, 0);
        glTexCoord2f(TEXTURE_SIZE, TEXTURE_SIZE);
        glVertex3f(sx + BLOCK_WIDTH * 4, sy - BLOCK_WIDTH * 4, 0);
        glTexCoord2f(0, TEXTURE_SIZE);
        glVertex3f(sx, sy - BLOCK_WIDTH * 4, 0);
        glEnd();
        sx += BLOCK_WIDTH * 4;
      }
      sy -= BLOCK_WIDTH * 4;
      by++;
    }
    glEnable(GL_BLEND);
    by = cast(int) screenY;
    oy = screenY - by;
    sy = BLOCK_WIDTH * SCREEN_BLOCK_SIZE_Y / 2 + oy;
    for (int y = 0; y < SCREEN_BLOCK_SIZE_Y; y++) {
      if (by >= BLOCK_SIZE_Y)
        by -= BLOCK_SIZE_Y;
      sx = -BLOCK_WIDTH * SCREEN_BLOCK_SIZE_X / 2;
      for (int bx = 0; bx < SCREEN_BLOCK_SIZE_X; bx++) {
        if (block[bx][by] >= 0) {
          glPushMatrix();
          glTranslatef(sx + BLOCK_WIDTH / 2, sy - BLOCK_WIDTH / 2, 0);
          int b = block[bx][by];
          if (b == 10)
            groundShape[11].draw();
          groundShape[b].draw();
          glPopMatrix();
        }
        sx += BLOCK_WIDTH;
      }
      sy -= BLOCK_WIDTH;
      by++;
    }
  }

  public void drawSideWalls() {
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    Screen.setColor(0, 0, 0, 1);
    glBegin(GL_TRIANGLE_FAN);
    glVertex3f(SIDEWALL_X1, SIDEWALL_Y, 0);
    glVertex3f(SIDEWALL_X2, SIDEWALL_Y, 0);
    glVertex3f(SIDEWALL_X2, -SIDEWALL_Y, 0);
    glVertex3f(SIDEWALL_X1, -SIDEWALL_Y, 0);
    glEnd();
    glBegin(GL_TRIANGLE_FAN);
    glVertex3f(-SIDEWALL_X1, SIDEWALL_Y, 0);
    glVertex3f(-SIDEWALL_X2, SIDEWALL_Y, 0);
    glVertex3f(-SIDEWALL_X2, -SIDEWALL_Y, 0);
    glVertex3f(-SIDEWALL_X1, -SIDEWALL_Y, 0);
    glEnd();
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
  }

  private void createBlocks() {
    for (int y = nextBlockY; y < nextBlockY + NEXT_BLOCK_AREA_SIZE; y++) {
      int by = y % BLOCK_SIZE_Y;
      for (int bx = 0; bx < BLOCK_SIZE_X; bx++)
        block[bx][by] = -1;
    }
    panelPosNum = 0;
    if (ship.toGround)
      return;
    int type = rand.nextInt(3);
    for (int i = 0; i < 2 + rand.nextInt(2); i++)
      addGround(type);
    for (int y = nextBlockY; y < nextBlockY + NEXT_BLOCK_AREA_SIZE; y++) {
      int by = y % BLOCK_SIZE_Y;
      for (int bx = 0; bx < BLOCK_SIZE_X; bx++) {
        if (y == nextBlockY || y == nextBlockY + NEXT_BLOCK_AREA_SIZE - 1)
          block[bx][by] = -1;
      }
    }
    for (int y = nextBlockY; y < nextBlockY + NEXT_BLOCK_AREA_SIZE; y++) {
      int by = y % BLOCK_SIZE_Y;
      for (int bx = 0; bx < BLOCK_SIZE_X - 1; bx++) {
        if (block[bx][by] == 0) {
          bool b1 = checkBlock(bx, by - 1);
          bool b2 = checkBlock(bx + 1, by);
          bool b3 = checkBlock(bx, by + 1);
          bool b4 = checkBlock(bx - 1, by);
          if ((b1 && !b2 && !b3 && !b4) || (!b1 && b2 && !b3 && !b4) ||
              (!b1 && !b2 && b3 && !b4) || (!b1 && !b2 && !b3 && b4))
            block[bx][by] = -1;
        }
      }
      for (int bx = BLOCK_SIZE_X - 1; bx >= 0; bx--) {
        if (block[bx][by] == 0) {
          bool b1 = checkBlock(bx, by - 1);
          bool b2 = checkBlock(bx + 1, by);
          bool b3 = checkBlock(bx, by + 1);
          bool b4 = checkBlock(bx - 1, by);
          if ((b1 && !b2 && !b3 && !b4) || (!b1 && b2 && !b3 && !b4) ||
              (!b1 && !b2 && b3 && !b4) || (!b1 && !b2 && !b3 && b4))
            block[bx][by] = -1;
        }
      }
      for (int bx = 0; bx < BLOCK_SIZE_X; bx++) {
        if (block[bx][by] == 0) {
          int b;
          bool b1 = checkBlock(bx, by - 1);
          bool b2 = checkBlock(bx + 1, by);
          bool b3 = checkBlock(bx, by + 1);
          bool b4 = checkBlock(bx - 1, by);
          if (!b1 && b2 && b3 && !b4)
            b = 0;
          else if (!b1 && !b2 && b3 && b4)
            b = 2;
          else if (b1 && !b2 && !b3 && b4)
            b = 4;
          else if (b1 && b2 && !b3 && !b4)
            b = 6;
          else if (b1 && b2 && b3 && b4)
            b = 11;
          else
            b = 8;
          block[bx][by] = b;
          if (b == 11) {
            panelPos[panelPosNum].x = bx;
            panelPos[panelPosNum].y = by;
            panelPosNum++;
          }
        }
      }
    }
  }

  private void gotoNextBlockArea() {
    blockCreateCnt += NEXT_BLOCK_AREA_SIZE;
    nextBlockY -= NEXT_BLOCK_AREA_SIZE;
    if (nextBlockY < 0)
      nextBlockY += BLOCK_SIZE_Y;
  }

  private void addGround(int type) {
    int cx;
    switch (type) {
    case 0:
      cx = rand.nextInt(cast(int) (BLOCK_SIZE_X * 0.4f)) + cast(int) (BLOCK_SIZE_X * 0.1f);
      break;
    case 1:
      cx = rand.nextInt(cast(int) (BLOCK_SIZE_X * 0.4f)) + cast(int) (BLOCK_SIZE_X * 0.5f);
      break;
    case 2:
      if (rand.nextInt(2) == 0)
        cx = rand.nextInt(cast(int) (BLOCK_SIZE_X * 0.4f)) - cast(int) (BLOCK_SIZE_X * 0.2f);
      else
        cx = rand.nextInt(cast(int) (BLOCK_SIZE_X * 0.4f)) + cast(int) (BLOCK_SIZE_X * 0.8f);
      break;
    }
    int cy = rand.nextInt(cast(int) (NEXT_BLOCK_AREA_SIZE * 0.6f)) + cast(int) (NEXT_BLOCK_AREA_SIZE * 0.2f);
    cy += nextBlockY;
    int w = rand.nextInt(cast(int) (BLOCK_SIZE_X * 0.33f)) + cast(int) (BLOCK_SIZE_X * 0.33f);
    int h = rand.nextInt(cast(int) (NEXT_BLOCK_AREA_SIZE * 0.24f)) + cast(int) (NEXT_BLOCK_AREA_SIZE * 0.33f);
    cx -= w / 2;
    cy -= h / 2;
    float wr, hr;
    for (int y = nextBlockY; y < nextBlockY + NEXT_BLOCK_AREA_SIZE; y++) {
      int by = y % BLOCK_SIZE_Y;
      for (int bx = 0; bx < BLOCK_SIZE_X; bx++) {
        if (bx >= cx && bx < cx + w && y >= cy && y < cy + h) {
          float o, to;
          wr = rand.nextFloat(0.2f) + 0.2f;
          hr = rand.nextFloat(0.3f) + 0.4f;
          o = (bx - cx) * wr + (y - cy) * hr;
          wr = rand.nextFloat(0.2f) + 0.2f;
          hr = rand.nextFloat(0.3f) + 0.4f;
          to = (cx + w - 1 - bx) * wr + (y - cy) * hr;
          if (to < o)
            o = to;
          wr = rand.nextFloat(0.2f) + 0.2f;
          hr = rand.nextFloat(0.3f) + 0.4f;
          to = (bx - cx) * wr + (cy + h - 1 - y) * hr;
          if (to < o)
            o = to;
          wr = rand.nextFloat(0.2f) + 0.2f;
          hr = rand.nextFloat(0.3f) + 0.4f;
          to = (cx + w - 1 - bx) * wr + (cy + h - 1 - y) * hr;
          if (to < o)
            o = to;
          if (o > 1)
            block[bx][by] = 0;
        }
      }
    }
  }

  private bool checkBlock(int x, int y) {
    if (x < 0 || x >= BLOCK_SIZE_X)
      return false;
    int by = y;
    if (by < 0)
      by += BLOCK_SIZE_Y;
    if (by >= BLOCK_SIZE_Y)
      by -= BLOCK_SIZE_Y;
    return (block[x][by] > -1);
  }

  public bool checkInField(Vector p) {
    return _size.contains(p);
  }

  public bool checkInField(float x, float y) {
    return _size.contains(x, y);
  }

  public bool checkInOuterField(Vector p) {
    return _outerSize.contains(p);
  }

  public Vector size() {
    return _size;
  }

  public Vector outerSize() {
    return _outerSize;
  }

  public float lastScrollY() {
    return _lastScrollY;
  }
}

Generated by  Doxygen 1.6.0   Back to index