Blob Blame Raw

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <helianthus.h>


Sprite player;
Group walls;
Group boxes;
Group places;

Animation animPlayer;
Animation animWall;
Animation animBox;
Animation animPlace;

Font font;


double speed = 256;
int level = 0;


void loadLevel() {
  FILE *f = NULL;
  Directory dir = openDirectoryEx("data/levels/sokoban", "", ".level", FALSE, TRUE, FALSE);
  if (dir) {
    int count = directoryGetCount(dir);
    if (count > 0) {
      if (level >= count) level = 0;
      if (level < 0) level = count - 1;
      f = fopen(directoryGetFull(dir, level), "r");
    }
    closeDirectory(dir);
  }

  if (!f) {
    messageBox("Cannot open level file");
    return;
  }

  groupDestroyEach(walls);
  groupDestroyEach(boxes);
  groupDestroyEach(places);

  int c;
  int x = 32;
  int y = 32;
  int maxX = 0, maxY = 0;
  Sprite s;
  do {
    c = fgetc(f);

    if (c == '\n') { y += 64; x = 32; continue; }

    if (c == '.') {
      s = createSpriteEx(x, y, 10, 10, animPlace);
      spriteSetColliderCircle(s, 0, 0, -1);
      spriteSetDepth(s, 1);
      groupAdd(places, s);
    } else
    if (c == '#') {
      s = createSpriteEx(x, y, 64, 64, animWall);
      spriteSetMassLevel(s, 100);
      groupAdd(walls, s);
      if (maxX < x) maxX = x;
      if (maxY < y) maxY = y;
    } else
    if (c == 'B') {
      s = createSpriteEx(x, y, 62, 62, animBox);
      spriteSetColliderRectangle(s, 0, 0, 0, -1, -1, 16);
      groupAdd(boxes, s);
    } else
    if (c == '@') {
      spriteSetXY(player, x, y);
    }

    x += 64;
  } while (c != EOF);
  fclose(f);

  windowSetWidth(maxX + 32);
  windowSetHeight(maxY + 32);
}


void init() {
  background(colorByName("black"));

  animPlayer = createAnimation("data/sprite/breadball.png");
  animWall = createAnimation("data/sprite/bricks-tile.png");
  animBox = createAnimation("data/sprite/box.png");
  animPlace = createAnimation("data/sprite/dot.png");

  font = createFont("data/fonts/blackcry.ttf");
  textFont(font);

  player = createSpriteEx(0, 0, 62, 62, animPlayer);
  spriteSetColliderCircle(player, 0, 0, -1);

  walls = createGroup();
  boxes = createGroup();
  places = createGroup();

  loadLevel();
}


void draw() {
  double dt = windowGetFrameTime();

  double x = spriteGetX(player);
  double y = spriteGetY(player);
  double step = speed*dt;
  if (keyDown("left")) {
    spriteSetMirrorX(player, -1);
    spriteSetX(player, x - step);
  }
  if (keyDown("right")) {
    spriteSetMirrorX(player, 1);
    spriteSetX(player, x + step);
  }
  if (keyDown("up")) {
    spriteSetY(player, y - step);
  }
  if (keyDown("down")) {
    spriteSetY(player, y + step);
  }

  if (keyWentDown("r")) {
      loadLevel();
  }
  if (keyWentDown("pageup")) {
      --level;
      loadLevel();
  }
  if (keyWentDown("pagedown")) {
      ++level;
      loadLevel();
  }

  groupCollide(walls, player);
  groupCollide(boxes, player);
  groupCollideBetween(boxes);
  groupCollideGroup(walls, boxes);

  drawSprites();

  noFill();
  stroke(colorByName("white"));
  textAlign(HALIGN_CENTER, VALIGN_BOTTOM);
  text(windowGetWidth()/2, windowGetHeight() - 10, "R - restart level, PgUp - previous level, PgDown - next level");
}


int main() {
  windowSetTitle("Sokoban");
	windowSetInit(&init);
	windowSetDraw(&draw);
	windowSetFrameRateEx(10, 100);
	windowRun();
	return 0;
}