conway game of life naive implementation

This commit is contained in:
wgroeneveld 2018-11-30 13:48:43 +01:00
parent be655e9efe
commit 0bab9368ba
13 changed files with 391 additions and 4 deletions

View File

@ -30,4 +30,5 @@ add_subdirectory(test)
add_subdirectory(demos/demo1-basicfeatures)
add_subdirectory(demos/demo2-arkanoid)
add_subdirectory(demos/demo3-foodthrowing)
add_subdirectory(demos/demo3-foodthrowing)
add_subdirectory(demos/demo4-conway)

View File

@ -0,0 +1,11 @@
project(conway)
add_executable(${PROJECT_NAME}.elf
src/main.cpp
src/ConwayScene.cpp src/ConwayScene.h src/bg.h src/ConwaySeeder.cpp src/ConwaySeeder.h)
target_link_libraries(${PROJECT_NAME}.elf gba-sprite-engine)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -v -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.gba
)

View File

@ -0,0 +1,58 @@
/* conway.h
* generated by png2gba program */
#define conway_width 24
#define conway_height 8
const unsigned char conway_data [] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
};
const unsigned short conway_palette [] = {
0x7c1f, 0x0c7e, 0x0fd0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

View File

@ -0,0 +1,99 @@
//
// Created by Wouter Groeneveld on 30/11/18.
//
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/sprites/sprite_builder.h>
#include <libgba-sprite-engine/gba/tonc_core.h>
#include <libgba-sprite-engine/background/text_stream.h>
#include "ConwayScene.h"
#include "bg.h"
// See http://www.coranac.com/tonc/text/gfx.htm#cd-qran
int __qran_seed= 42; // Seed / rnd holder
ConwayScene::ConwayScene(const std::shared_ptr<GBAEngine> &engine, u8 percentageSeed) : Scene(engine), percentageSeed(percentageSeed) {
}
std::vector<Sprite *> ConwayScene::sprites() {
return {};
}
std::vector<Background *> ConwayScene::backgrounds() {
return { bg.get() };
}
int ConwayScene::countAmountOfNeighbouringCellsAlive(int x, int y) {
int amountOfNeightbouringCellsAlive = 0;
int pos = y * MAP_WIDTH + x;
for(int x_i = x - 1; x_i <= x + 1; x_i++) {
for(int y_j = y - 1; y_j <= y + 1; y_j++) {
int toCheckPos = y_j * MAP_WIDTH + x_i;
if(toCheckPos >= 0 && toCheckPos < MAP_SIZE - 1 && pos != toCheckPos && map[toCheckPos] == ALIVE) {
amountOfNeightbouringCellsAlive++;
}
}
}
return amountOfNeightbouringCellsAlive;
}
u16 ConwayScene::getNextState(int x, int y) {
int pos = y * MAP_WIDTH + x;
int amountAlive = countAmountOfNeighbouringCellsAlive(x, y);
int currentState = map[pos];
if(currentState == DEAD) {
if(amountAlive == 3) {
return ALIVE;
}
return DEAD;
} else {
if (amountAlive < 2 || amountAlive > 3) {
return DEAD;
}
return ALIVE;
}
}
void ConwayScene::seedRandomMap(int seedcount) {
for(int i = 0; i < MAP_SIZE; i++) {
map[i] = DEAD;
}
for(int i = 0; i < seedcount; i++) {
int x = qran_range(0, MAP_WIDTH);
int y = qran_range(0, MAP_HEIGHT);
map[y * MAP_WIDTH + x] = ALIVE;
}
}
void ConwayScene::load() {
backgroundPalette = std::unique_ptr<BackgroundPaletteManager>(new BackgroundPaletteManager(conway_palette, sizeof(conway_palette)));
seedRandomMap(((MAP_WIDTH * MAP_HEIGHT) / 100) * percentageSeed);
bg = std::unique_ptr<Background>(new Background(1, conway_data, sizeof(conway_data), map, sizeof(map)));
bg.get()->useMapScreenBlock(16);
}
void ConwayScene::tick(u16 keys) {
generation++;
int totalAmountAlive = 0;
dma3_cpy(buffer, map, sizeof(buffer));
for(int w = 0; w < MAP_WIDTH; w++) {
for(int h = 0; h < MAP_HEIGHT; h++) {
u16 state = getNextState(w, h);
if(state == ALIVE) totalAmountAlive++;
buffer[h * MAP_WIDTH + w] = state;
}
}
TextStream::instance().setText(std::string("amount alive: ") + std::to_string(totalAmountAlive) + std::string(" of ") + std::to_string(MAP_SIZE), 1, 1);
TextStream::instance().setText(std::string("generation: ") + std::to_string(generation), 2, 1);
dma3_cpy(map, buffer, sizeof(map));
bg.get()->updateMap(buffer);
}

View File

@ -0,0 +1,41 @@
//
// Created by Wouter Groeneveld on 30/11/18.
//
#ifndef GBA_SPRITE_ENGINE_PROJECT_CONWAYSCENE_H
#define GBA_SPRITE_ENGINE_PROJECT_CONWAYSCENE_H
#define MAP_WIDTH 64
#define MAP_HEIGHT 64
#define MAP_SIZE 64 * 64
#define ALIVE 0x0001
#define DEAD 0x0002
#include <libgba-sprite-engine/scene.h>
class ConwayScene : public Scene {
private:
u8 percentageSeed;
u16 generation;
std::unique_ptr<Background> bg;
u16 map[MAP_SIZE], buffer[MAP_SIZE];
int countAmountOfNeighbouringCellsAlive(int x, int y);
void seedRandomMap(int seedcount);
u16 getNextState(int x, int y);
public:
ConwayScene(const std::shared_ptr<GBAEngine> &engine, u8 percentageSeed);
std::vector<Sprite *> sprites() override;
std::vector<Background *> backgrounds() override;
void load() override;
void tick(u16 keys) override;
};
#endif //GBA_SPRITE_ENGINE_PROJECT_CONWAYSCENE_H

View File

@ -0,0 +1,55 @@
//
// Created by Wouter Groeneveld on 30/11/18.
//
#include <libgba-sprite-engine/sprites/sprite_builder.h>
#include <libgba-sprite-engine/background/text_stream.h>
#include <libgba-sprite-engine/gba/tonc_memdef.h>
#include <libgba-sprite-engine/gba_engine.h>
#include "ConwaySeeder.h"
#include "bg.h"
#include "ConwayScene.h"
ConwaySeeder::ConwaySeeder(const std::shared_ptr<GBAEngine> &engine) : Scene(engine), percentage(30), delta(0) {}
std::vector<Background *> ConwaySeeder::backgrounds() {
return {};
}
std::vector<Sprite *> ConwaySeeder::sprites() {
return {
conwaySprite.get()
};
}
void ConwaySeeder::load() {
foregroundPalette = std::unique_ptr<ForegroundPaletteManager>(new ForegroundPaletteManager(conway_palette, sizeof(conway_palette)));
SpriteBuilder<Sprite> builder;
conwaySprite = builder
.withData(conway_data, sizeof(conway_data))
.withSize(SIZE_32_8)
.withLocation(GBA_SCREEN_WIDTH - 40, 8)
.buildPtr();
TextStream::instance().setText(std::string("Conways Game of Life"), 1, 1);
TextStream::instance().setText(std::string("Up/Down to adjust"), 10, 1);
TextStream::instance().setText(std::string("Start to render"), 11, 1);
}
void ConwaySeeder::tick(u16 keys) {
TextStream::instance().setText(std::string("Seed percentage: ") + std::to_string(percentage), 5, 1);
if(keys & KEY_START) {
engine.get()->setScene(new ConwayScene(engine, percentage));
} else if(keys & KEY_UP && percentage < 90) {
delta = 1;
} else if(keys & KEY_DOWN && percentage > 10) {
delta = -1;
} else {
if(delta != 0) {
percentage += 10 * delta;
delta = 0;
}
}
}

View File

@ -0,0 +1,31 @@
//
// Created by Wouter Groeneveld on 30/11/18.
//
#ifndef GBA_SPRITE_ENGINE_PROJECT_CONWAYSEEDER_H
#define GBA_SPRITE_ENGINE_PROJECT_CONWAYSEEDER_H
#include <libgba-sprite-engine/scene.h>
class ConwaySeeder : public Scene {
private:
int delta;
int percentage;
std::unique_ptr<Sprite> conwaySprite;
public:
ConwaySeeder(const std::shared_ptr<GBAEngine> &engine);
std::vector<Sprite *> sprites() override;
std::vector<Background *> backgrounds() override;
void load() override;
void tick(u16 keys) override;
};
#endif //GBA_SPRITE_ENGINE_PROJECT_CONWAYSEEDER_H

View File

@ -0,0 +1,66 @@
//
// Created by Wouter Groeneveld on 30/11/18.
//
#ifndef GBA_SPRITE_ENGINE_PROJECT_BG_H
#define GBA_SPRITE_ENGINE_PROJECT_BG_H
/* conway.h
* generated by png2gba program */
#define conway_width 24
#define conway_height 8
const unsigned char conway_data [] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
};
const unsigned short conway_palette [] = {
0x7c1f, 0x0c7e, 0x0fd0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000
};
#endif //GBA_SPRITE_ENGINE_PROJECT_BG_H

View File

@ -0,0 +1,19 @@
//
// Created by Wouter Groeneveld on 30/11/18.
//
#include "ConwaySeeder.h"
#include <libgba-sprite-engine/gba_engine.h>
int main() {
std::shared_ptr<GBAEngine> engine(new GBAEngine());
ConwaySeeder* startScene = new ConwaySeeder(engine);
engine->setScene(startScene);
while (true) {
engine->update();
}
return 0;
}

View File

@ -29,6 +29,7 @@ public:
Background(int bgIndex, const void *data, int size, const void* map, int mapSize) : data(data), bgIndex(bgIndex), size(size), map(map),
screenBlockIndex(0), charBlockIndex(0), mapSize(mapSize) {}
virtual void persist();
void updateMap(const void* map);
void clearMap();
void clearData();
};

View File

@ -26,6 +26,11 @@ void* char_block(unsigned long block) {
return (void*) (0x6000000 + (block * 0x4000));
}
void Background::updateMap(const void *map) {
this->map = map;
dma3_cpy(screen_block(screenBlockIndex), this->map, this->mapSize);
}
void Background::persist() {
dma3_cpy(char_block(bgIndex), this->data, this->size);

View File

@ -145,11 +145,11 @@ void GBAEngine::setScene(Scene* scene) {
dequeueAllSounds();
if(this->currentScene) {
cleanupPreviousScene();
if(!this->disableTextBg) {
TextStream::instance().clear();
}
}
scene->load();
if(!this->disableTextBg) {
TextStream::instance().clear();
}
auto fgPalette = scene->getForegroundPalette();
if(!fgPalette) {