let myStorage = window.localStorage;
myStorage.setItem('player_state', player.stateId);
myStorage.removeItem('player_state');
myStorage.clear();
await db.players.add({
name: 'DoDo',
avatar: await getBlob('dodo.png'),
key_mapping: 'default'
});
// p_saveg.c::P_UnArchiveThinkers
while (1) {
tclass = *save_p++;
switch (tclass) {
case tc_mobj:
PADSAVEP();
mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
memcpy (mobj, save_p, sizeof(*mobj));
save_p += sizeof(*mobj);
mobj->state = &states[(int)mobj->state];
mobj->target = NULL;
if (mobj->player) {
mobj->player = &players[(int)mobj->player-1];
mobj->player->mo = mobj;
}
P_SetThingPosition (mobj);
mobj->info = &mobjinfo[mobj->type];
P_AddThinker (&mobj->thinker);
Grid-based map in .txt file
// iterating inside out -> SLOW
for (i = 0 to size)
for (j = 0 to size)
do something with array[j][i]
// iterating outside in -> FAST
for (i = 0 to size)
for (j = 0 to size)
do something with array[i][j]
// assume only 50% active/visible objects
gameLoop(delta, absolute) {
for(var entity in this.entities) {
// 50% mispredictions
if(entity.ACTIVE) {
entity.update(delta, absolute);
}
if(entity.VISIBLE) {
entity.draw();
}
}
}
class Brainbot extends Unit {
private damage: number;
private currentWeapon: WeaponType;
constructor() {
super(UnitType.BRAIN_BOT);
}
init(attributes: UnitAttribs) {
// set default values
this.damage = DEFAULT_DAMAGE_BRAINBOT;
this.currentWeapon = WeaponType.LASERGUN;
this.attributes = attributes;
}
}
if(asteroid.position.distance(rocket.position) <= MIN_PROXIMITY) { // detect proximity
rocket.runAnimation(ANIM_EXPLOSION); // react instantly and handle everything
asteroid.runAnimation(ANIM_EXPLOSION);
playSound(SOUND_EXPLOSION);
asteroid.delete();
rocket.delete();
}
let collisions = this.collisionSystem.checkProximity(allGameObjects);
collisions.forEach(colliding => this.sendEvent(COLLISION_TRIGGERED, colliding));
// rocket-handler.ts
onCollisionTriggered(colliding) {
this.destroy();
this.sendEvent(ROCKET_DESTROYED);
}
// sound-component.ts
onGameObjectDestroyed() {
this.playSound(SOUND_EXPLOSION);
}
public class Generator {
private final static AtomicInteger counter = new AtomicInteger();
public static int getId() {
return counter.incrementAndGet();
}
}
function* generateId() {
let id = 0;
while(true) {
yield id;
id++;
}
}
let newId = generateId().next();
class Generator {
static idCounter = 0;
getId(): number {
return Generator.idCounter++;
}
}
// stateless, the creature will jump each frame
creatureUpdate(delta: number, absolute: number) {
if(pressedKeys.has(KeyCode.UP)) {
this.creature.jump();
}
}
// a variable that makes certain actions possible only according to the current state
creatureUpdate(delta: number, absolute: number) {
if(pressedKeys.has(KeyCode.UP) && this.creature.state !== STATE_JUMPING) {
this.creature.changeState(STATE_JUMPING);
this.creature.jump();
}
}
void Node::MarkDirty() {
// a) whenever a node is marked dirty, all its children are marked dirty as well.
// b) whenever a node is cleared from being dirty, all its parents must have been
// cleared as well.
if (this->dirty_) return;
this->dirty_ = true;
// Notify listener components first, then mark child nodes
for (auto i = this->listeners_.Begin(); i != this->listeners_.End();) {
Component *c = *i;
if (c) {
c->OnMarkedDirty(this);
++i;
} else {
*i = this->listeners_.Back(); // listener expired -> erase from list
this->listeners_.Pop();
}
}
// Mark all children dirty
for(auto child : children) {
child->MarkDirty();
}
}
addChild(child) {
// if the child has a parent then lets remove it as PixiJS objects can only exist in one place
if (child.parent) {
child.parent.removeChild(child);
}
child.parent = this;
this.sortDirty = true;
...
this.emit('childAdded', child, this, this.children.length - 1);
child.emit('added', this);
return child;
}
updateTransform() {
if (this.sortableChildren && this.sortDirty) {
this.sortChildren();
}
...
}
// hashing function
inline unsigned SDBMHash(unsigned hash, unsigned char c)
{ return c + (hash << 6) + (hash << 16) - hash; }
unsigned calc(const char* str, unsigned hash = 0) {
while (*str) {
// Perform the current hashing as case-insensitive
char c = *str;
hash = SDBMHash(hash, (unsigned char)tolower(c));
++str;
}
return hash;
}
class Builder {
private _position: Vector;
private _scale: Vector;
position(pos: Vector) {
this.position = pos;
return this;
}
scale(scale: Vector) {
this.scale = scale;
return this;
}
build() {
return new GameObject(this._position, this._scale);
}
}
new Builder().position(new Vector(12, 54)).scale(new Vector(2, 1)).build();
class UnitFactory {
private pikemanBuilder: Builder; // preconfigured to build pikemans
private musketeerBuilder: Builder; // preconfigured to build musketeers
private archerBuilder: Builder; // preconfigured to build archers
public spawnPikeman(position: Vector, faction: FactionType): GameObject {
return this.pikeman.position(position).faction(faction).build();
}
public spawnMusketeer(position: Vector, faction: FactionType): GameObject {
return this.musketeerBuilder.position(position).faction(faction).build();
}
public spawnArcher(position: Vector, faction: FactionType): GameObject {
return this.archerBuilder.position(position).faction(faction).build();
}
}
class UnitFactory {
private pikemanBuilder: Builder;
private musketeerBuilder: Builder;
private archerBuilder: Builder;
public initBuilders() {
// sprites are shared, weapons must be instantiated for each instance
this.pikemanBuilder.sprite(Sprites.PIKEMAN).weapon(() => new Spear());
this.musketeerBuilder.sprite(Sprites.Musketeer).weapon(() => new Musket());
this.archerBuilder.sprite(Sprites.ARCHER).weapon(() => new Bow());
}
...
}
Rampart (1990)
Dungeon Defenders 2 (2017)
Arcane Archer Cannon Crossbow Dark
Gremlin Goblin Imp Giant
I'm blind, not deaf