Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
tutorial: elementary scripts
This time, we will not need custom C++ classes, we will use the scripting system of libgeds to tell which spriteset and tileset to load, and to instanciate an animated character. Demo.cmd is the main script doing all this. It requires a sub-script describing the "state machine" for the animated character "xdad.cmd". Such a sub-script gets its own set of animation and state identifiers, which the root script can later 'import' selectively. At least one state of the sub-script needs to be imported if you want to be able to create new instances of the character.

Instantiation is performed through the `gob<instance-id> :state<global-state-id>(<coordinates>) <cast>` line. This will lookup the given state, decide what sort of back-end code is required to process the state machine (in this case a SimpleGob) and creates it, linking it to the given state.

As a result, the `Hero` class is no longer required, nor is explicit loading of SpriteSet. Resources are now managed directly by the GameScript class, according to the `spr.<command>` and `bg<layer-id>.<command>` lines of the script. Admittedly, the new character cannot move yet. We will solve this with appropriate state machine rules in upcoming tutorials.

The glu logic to manipulate the GameScript is implemented through two 'window' classes(both defined in GameWindow.hpp), one for parsing and running the level (GameWindow), and the other to handle level-to-level transition (LoadingWindow). We can get the script running simply by "switching" to the GameWindow (using Engine::setWindow) once the appropriate FileReader has been created.

You will note a few changes regarding the 'background' initialization:
- we now have to explictly call `restore()` in the code, because we no longer ask the engine to switch to the MetaWindow.
- the GameScript do use the BG2 for its own purpose, and loads tileset there. However, the settings are slightly different from what we did before. The tileset gets loaded
at a higher location (address) in video memory. We could initialize `tile = 512`, but we can also tell the hardware to interprete the tile number "3" differently (2 * 256 + 3) by setting the BG_TILE_BASE field of the background layer control register.
- this is also temporarily. We'll do more interesting backgrounds using maps created by the Level Editor for DS in an upcoming tutorial.
  • Loading branch information
PypeBros committed Apr 3, 2018
1 parent 06fe497 commit 40176d5
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Demo/Makefile
Expand Up @@ -31,7 +31,7 @@ $M-clean:
# main targets
#---------------------------------------------------------------------------------

$(TARGET).nds : $(TARGET).arm9 $(PPP7)
$(TARGET).nds : $(TARGET).arm9 $(PPP7) $(wildcard $(ROOT)/$M/efsroot/*.cmd)
$(TARGET).arm9 : $(TARGET).elf
$(TARGET).elf : $(OFILES) $(LIBDEPS)

Expand Down
18 changes: 18 additions & 0 deletions Demo/efsroot/demo.cmd
@@ -0,0 +1,18 @@
# -*- sh -*-
# simple demo script. With no maps yet, there isn't much to demonstrate ^^"
#
print "loading level1"
bg0.load "../bg.spr"
print "loading sprites"
spr.load "../hero.spr":1

print "declaring state machine"

input "xdad.cmd"
import state 0
print "creating gobs"
gob0 :state0 (128, 100) h # rightmost
focus=gob0
print "go!"

end
25 changes: 25 additions & 0 deletions Demo/efsroot/xdad.cmd
@@ -0,0 +1,25 @@

anim1 0 {
spr0 4
delay 3
spr0 5
delay 3
spr0 6
delay 3
spr0 7
delay 3
spr0 8
delay 3
spr0 9
delay 3
spr0 a
delay 3
spr0 b
delay 3
loop
}

state0 :anim1


end
84 changes: 18 additions & 66 deletions Demo/source/main.cpp
Expand Up @@ -20,6 +20,7 @@
#include "interfaces.h"
#include "GameObject.h"
#include "GameScript.h"
#include "GameWindow.hpp"

const char * UsingParsing::default_dir="efs:/";

Expand Down Expand Up @@ -55,63 +56,14 @@ Engine ge((GuiConfig)(CONSOLE_DOWN|MORE_BG_MEMORY));

class MetaWindow;

class Hero : public GameObject, UsingSprites {
NOCOPY(Hero);
const SpritePage *page;
unsigned x, y;
oamno_t oam;
unsigned frame;
public:
Hero(const SpritePage *pg)
: GameObject(HERO, 0, "hero"),
page(pg), x(128), y(96),
oam((oamno_t) gResources->allocate(RES_OAM)),
frame(0)
{
page->setOAM((blockno_t)2, sprites);

}

void dump(const char* why) {
}

void setxy(int _x, int _y) {
x = _x; y = _y;
}

donecode play(void) {
uint keys = keysHeld()|keysDown();
static const unsigned NFRAMES = 8;
static int walking[NFRAMES] = { 4, 5, 6, 7, 8, 9, 10, 11 };
int dx=0, dy=0;

if (keys & KEY_UP) {
dy = -4;
}
if (keys & KEY_DOWN) {
dy = 4;
}
if (keys & KEY_LEFT) {
dx = -4;
}
if (keys & KEY_RIGHT) {
dx = 4;
}
x += dx; y += dy;
page->changeOAM(sprites + oam, x, y,
(blockno_t) walking[((frame++)/3) % NFRAMES]);
return Animator::QUEUE;
}
};

class MetaWindow : public DownWindow {
NOCOPY(MetaWindow);
/* declare your 'xxxWindow' objects here. */
Window *active;
SpriteRam sprRam;
SpriteSet sprSet;
Hero *hero;
GameScript script;
InputReader* reader;
LoadingWindow loadwin;
GameWindow gamewin;

public:

/** in the 'PPP Engine' framework, core activities are handled in Windows that can
Expand All @@ -120,12 +72,15 @@ class MetaWindow : public DownWindow {
** the application should run when.
**/
MetaWindow(): active(0),
sprRam(SPRITE_GFX), sprSet(&sprRam, SPRITE_PALETTE),
hero(0), script(0)
reader(0),
loadwin(&reader),
gamewin(this, &reader, &loadwin)

{
/** there is no EFS yet at this point */
iprintf("creating windows -- ");
ntxm9 = new NTXM9();
active = this;
active = &gamewin;
}

virtual bool event(Widget *w, uint id) {
Expand All @@ -137,20 +92,15 @@ class MetaWindow : public DownWindow {


void setactive() {
SpriteRam myRam(WIDGETS_CHARSET(512));
SpriteSet mySet(&myRam, BG_PALETTE);
mySet.Load("efs:/bg.spr");
sprSet.Load("efs:/hero.spr");

/** there's only one music file in this project.
**/
FileDataReader fd("efs:/sndtrk.xm");
reader = new FileReader("efs:/demo.cmd");
ntxm9->stop();
u16 err = ntxm9->load(&fd);
ge.setWindow(active);
restore();
if (err!=0) iprintf("ntxm says %x\n",err);
hero = new Hero(sprSet.getpage(PAGE0));
hero->run()->regAnim(true);
}


Expand All @@ -173,7 +123,6 @@ class MetaWindow : public DownWindow {
iprintf("%s(%x) @p%i:r%i:c%i\n",code?"oops":"okay",code,pat,row,chn);
return true;
}

if (keys&KEY_B) {
defaultExceptionHandler();
iprintf("beware the guru\n");
Expand All @@ -186,8 +135,11 @@ class MetaWindow : public DownWindow {
virtual void restore() {
iprintf("(A) play (Y) stop (X) info (B) dump\n");
REG_DISPCNT|=DISPLAY_BG2_ACTIVE;
REG_BG2CNT=BG_MAP_BASE(GEBGROUND)|BG_TILE_BASE(0)|BG_COLOR_256;
tileno_t tile = 256;
REG_BG2CNT=BG_MAP_BASE(GEBGROUND)|BG_TILE_BASE(2)|BG_COLOR_256;
tileno_t tile = 0;
for (int i = 0; i < 32*32; i++) {
WIDGETS_BACKGROUND[i] = 0;
}
for (int l=0; l<32; l+=2) {
for (int b=0; b<8; b+=2) {
WIDGETS_BACKGROUND[b+l*32]=tile++;
Expand Down

0 comments on commit 40176d5

Please sign in to comment.