ref: b545537c9a6c7d32976b863cbb14792980d31e3d
parent: 941d146cea7d0c2ce872e599622a5c9e01d37fe2
author: rodri <rgl@antares-labs.eu>
date: Wed Mar 8 15:59:10 EST 2023
implemented states to represent game scene stages. added an intro as well.
binary files /dev/null b/assets/spr/intro.pic differ
--- a/dat.h
+++ b/dat.h
@@ -58,7 +58,7 @@
typedef struct VModel VModel;
typedef struct Sprite Sprite;
typedef struct Keymap Keymap;
-typedef struct Scene Scene;
+typedef struct State State;
typedef struct Particle Particle;
typedef struct Bullet Bullet;
typedef struct Ship Ship;
@@ -107,14 +107,11 @@
KeyOp op;
};
-struct Scene
+struct State
{
- char *title;
- int state;
+ char *name;
- Scene *(*δ)(Scene*);
- void (*step)(Scene*);
- void (*draw)(Scene*);
+ State *(*δ)(State*, void*); /* transition fn */
};
struct Particle
--- a/musw.c
+++ b/musw.c
@@ -12,6 +12,14 @@
#include "dat.h"
#include "fns.h"
+enum {
+ GSIntro,
+ GSConnecting,
+ GSMatching,
+ GSPlaying,
+ NGAMESTATES
+};
+
Keymap kmap[] = {
{.key = Kup, .op = K↑},
{.key = Kleft, .op = K↺},
@@ -31,12 +39,15 @@
VModel *needlemdl, *wedgemdl;
Image *screenb;
Image *skymap;
-Scene *curscene;
+Sprite *intro;
+State gamestates[NGAMESTATES];
+State *gamestate;
Channel *ingress;
Channel *egress;
NetConn netconn;
char deffont[] = "/lib/font/bit/pelm/unicode.9.font";
char winspec[32];
+int weplaying;
int doghosting;
int debug;
@@ -365,6 +376,8 @@
switch(frame->type){
case NSsimstate:
+ weplaying = 1;
+
bufp = frame->data;
bufp += unpack(bufp, frame->len, "PdPdP",
&universe->ships[0].p, &universe->ships[0].θ,
@@ -385,6 +398,7 @@
break;
case NSbuhbye:
+ weplaying = 0;
netconn.state = NCSDisconnected;
break;
}
@@ -499,13 +513,20 @@
else
draw(screenb, screenb->r, skymap, nil, ZP);
- if(netconn.state == NCSConnecting)
+ switch(gamestate-gamestates){
+ case GSIntro:
+ intro->draw(intro, screenb, subpt(divpt(screenb->r.max, 2), divpt(intro->r.max, 2)));
+ break;
+ case GSConnecting:
drawconnecting();
-
- if(netconn.state == NCSConnected){
+ break;
+ case GSMatching:
+ break;
+ case GSPlaying:
drawship(&universe->ships[0], screenb);
drawship(&universe->ships[1], screenb);
universe->star.spr->draw(universe->star.spr, screenb, subpt(toscreen(universe->star.p), Pt(16,16)));
+ break;
}
draw(screen, screen->r, screenb, nil, ZP);
@@ -541,6 +562,37 @@
redraw();
}
+State *intro_δ(State *s, void *arg)
+{
+ double ∆t;
+ static ulong elapsed;
+
+ ∆t = *(double*)arg;
+ elapsed += ∆t/1e6;
+ if(elapsed > 5000)
+ return &gamestates[GSConnecting];
+ return s;
+}
+
+State *connecting_δ(State *s, void*)
+{
+ if(netconn.state != NCSConnecting)
+ return &gamestates[GSMatching];
+ return s;
+}
+
+State *matching_δ(State *s, void*)
+{
+ if(netconn.state == NCSConnected && weplaying)
+ return &gamestates[GSPlaying];
+ return s;
+}
+
+State *playing_δ(State *s, void*)
+{
+ return s;
+}
+
void
usage(void)
{
@@ -595,7 +647,6 @@
proccreate(kbdproc, nil, mainstacksize);
- /* TODO: implement this properly with screens and iodial(2) */
fd = dial(server, nil, nil, nil);
if(fd < 0)
sysfatal("dial: %r");
@@ -611,6 +662,14 @@
universe->ships[1].mdl = wedgemdl;
universe->star.spr = readsprite("assets/spr/earth.pic", ZP, Rect(0,0,32,32), 5, 20e3);
+ intro = readsprite("assets/spr/intro.pic", ZP, Rect(0,0,640,480), 1, 0);
+
+ gamestates[GSIntro].δ = intro_δ;
+ gamestates[GSConnecting].δ = connecting_δ;
+ gamestates[GSMatching].δ = matching_δ;
+ gamestates[GSPlaying].δ = playing_δ;
+ gamestate = &gamestates[GSIntro];
+
ingress = chancreate(sizeof(Frame*), 8);
egress = chancreate(sizeof(Frame*), 8);
threadcreate(threadnetrecv, &fd, mainstacksize);
@@ -626,15 +685,18 @@
frametime = now - then;
then = now;
- if(netconn.state != NCSConnected)
- lastpktsent += frametime/1e6;
+ if(gamestate != &gamestates[GSIntro]){
+ if(netconn.state == NCSConnecting)
+ lastpktsent += frametime/1e6;
- if(netconn.state == NCSDisconnected ||
- (netconn.state == NCSConnecting && lastpktsent >= 1000)){
- initconn();
- lastpktsent = 0;
+ if(netconn.state == NCSDisconnected ||
+ (netconn.state == NCSConnecting && lastpktsent >= 1000)){
+ initconn();
+ lastpktsent = 0;
+ }
}
+ gamestate = gamestate->δ(gamestate, &frametime);
universe->star.spr->step(universe->star.spr, frametime/1e6);
redraw();
--- a/todo
+++ b/todo
@@ -7,11 +7,14 @@
[ ] hyperjump
[ ] minskytron effect
[ ] engine damage on every jump
-[ ] different screens for each game state
- [ ] intro
- [ ] connecting to server
- [ ] waiting for a player
- [ ] main game
+[✓] different screens for each game state
+ [✓] intro
+ [✓] connecting to server
+ [✓] waiting for a player
+ [✓] main game
[ ] reduce the amount of data sent on every NSsimstate packet
[?] the client must try to connect continously
> there's an error in the udp stack that doesn't allow the client to receive packets if run before the server is up.
+[ ] more realistic DEC Type 30 CRT emulation
+ [ ] the right colors (fg: 0x3daaf7, fgblur: 0x0063eb, bg0: 0x79cc3e, bg1: 0x7eba1e)
+ [ ] the right decay function