ecs: default field values

This commit is contained in:
Steven Hugg 2022-02-20 10:15:16 -06:00
parent a444de693b
commit 07c0ae2f9c
4 changed files with 46 additions and 7 deletions

View File

@ -143,6 +143,7 @@ banks need to duplicate code and/or rodata
- don't split critical code across banks
need bank trampoline macro
nested scopes for game modes? (title / demo / play)
access parent data from child scope
critical data fields
if accessed in critical section, make critical
@ -150,4 +151,8 @@ ignore arrays that aren't referenced
use DASM for multipass?
default values for component fields
processes
take up at least one byte if stateful
might need free list
need jump table?
you'd like to change "mode" from any event

View File

@ -139,7 +139,12 @@ export class ECSCompiler extends Tokenizer {
let lo = this.expectInteger();
this.expectToken('..');
let hi = this.expectInteger();
return { dtype: 'int', lo, hi } as IntType;
// TODO: use default value?
let defvalue;
if (this.ifToken('default')) {
defvalue = this.expectInteger();
}
return { dtype: 'int', lo, hi, defvalue } as IntType;
}
if (this.peekToken().str == '[') {
return { dtype: 'ref', query: this.parseQuery() } as RefType;
@ -392,8 +397,7 @@ export class ECSCompiler extends Tokenizer {
entname = this.expectIdent().str;
}
let etype = this.parseEntityArchetype();
let entity = this.currentScope.newEntity(etype);
entity.name = entname;
let entity = this.currentScope.newEntity(etype, entname);
let cmd2: string;
// TODO: remove init?
while ((cmd2 = this.expectTokens(['const', 'init', 'var', 'decode', 'end']).str) != 'end') {

View File

@ -73,6 +73,24 @@ export class VCSSpriteDecoder extends LineDecoder {
}
}
export class VCSBitmapDecoder extends LineDecoder {
parse() {
let height = this.lines.length;
let bitmapdata = new Uint8Array(height);
for (let i=0; i<height; i++) {
this.curline = height - 1 - i;
let toks = this.lines[this.curline];
this.assertTokens(toks, 1);
bitmapdata[i] = this.decodeBits(toks[0], 8, true);
}
return {
properties: {
bitmapdata, height: height-1
}
}
}
}
export class VCSPlayfieldDecoder extends LineDecoder {
parse() {
let height = this.lines.length;
@ -178,6 +196,7 @@ export function newDecoder(name: string, text: string) : LineDecoder | undefined
const DECODERS = {
'vcs_sprite': VCSSpriteDecoder,
'vcs_bitmap': VCSBitmapDecoder,
'vcs_playfield': VCSPlayfieldDecoder,
'vcs_versatile': VCSVersatilePlayfieldDecoder,
'vcs_bitmap48': VCSBitmap48Decoder,

View File

@ -156,6 +156,7 @@ export interface IntType {
dtype: 'int'
lo: number
hi: number
defvalue?: number
}
export interface ArrayType {
@ -1088,15 +1089,18 @@ export class EntityScope implements SourceLocated {
) {
parent?.childScopes.push(this);
}
newEntity(etype: EntityArchetype): Entity {
newEntity(etype: EntityArchetype, name: string): Entity {
// TODO: add parent ID? lock parent scope?
// TODO: name identical check?
if (name && this.getEntityByName(name))
throw new ECSError(`already an entity named "${name}"`);
let id = this.entities.length;
etype = this.em.addArchetype(etype);
let entity: Entity = { id, etype, consts: {}, inits: {} };
for (let c of etype.components) {
this.componentsInScope.add(c.name);
}
entity.name = name;
this.entities.push(entity);
return entity;
}
@ -1172,7 +1176,14 @@ export class EntityScope implements SourceLocated {
} else {
array.ehi = i;
}
//console.log(i,e.name,array,cfname);
// set default values for entity/field
if (ftype == 'init') {
if (f.dtype == 'int' && f.defvalue !== undefined) {
let ecfname = mkscopesymbol(this, c, f.name);
if (e.inits[ecfname] == null)
this.setInitValue(e, c, f, f.defvalue);
}
}
}
}
// TODO: cull unused entity fields
@ -1323,7 +1334,7 @@ export class EntityScope implements SourceLocated {
let cfname = mksymbol(component, fieldName);
let ecfname = mkscopesymbol(this, component, fieldName);
if (e.consts[cfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a constant`, e);
if (e.inits[ecfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a`, e);
if (e.inits[ecfname] !== undefined) throw new ECSError(`"${fieldName}" is already defined as a variable`, e);
if (type == 'const') e.consts[cfname] = value;
if (type == 'init') e.inits[ecfname] = value;
this.fieldtypes[cfname] = type;