A web-based game with programmable bots (in Javascript). Live demo here.
- Choose the bots you want to fight (and you can add custom bots via URL)
- If you want to use a different ruleset, add it via the box at the bottom
- Press
Start
. - Hit the space bar to pause.
- Crusher
- Destroyer
- Dumbo: very simple bot
- Teleporter: for use with teleport ruleset
- SampleBot: empty bot
- Xavier
- default
- demo1: smaller bots, set obstacles, set initial placement, various parameter tweaks
- demo2: completely redone drawing code
- demo3: faster bullets, different look, CSS 3D transform
- conveyor: different strips of the world move bots up or down
- expulsion: adds teleportation circle in center of world, varying bot radii
- orbit: bots orbit around the center point
- teleport: adds "teleport" command (see the Teleporter bot)
- walls: moving walls, larger world
All bots inherit from the parent Bot class in bots/bot.js
. A bot script will be instantiated a number of times, depending on the ruleset.properties.bots.botsPerTeam
value.
- name: team name
- id: numeric id
- x, y: coordinates of the bot's current location
- color: the assigned team color (from the ruleset)
- angle: the bot's current angle in radians
- radius: size of bot
- health: from 0 to 100
- alive: boolean
- weapons: object with number of remaining ammo for each weapon type
- canShoot: boolean
- waitFire: number of clicks to wait before firing
- collided: boolean
- hitByBullet: boolean
this.distanceToPoint(x1, y1, x2, y2)
: returns distance from point 1 to point 2this.myDistanceToPoint(x, y)
: returns distance from the bot to the pointthis.getDirection(target, threshold)
: basic pathfinding helper function. Uses fields to avoid obstacles.target
needs to havex
andy
properties (point, bot, etc.). A threshold of0.05
works well. Returns an object:- response.command: the bot command needed to move closer to the target
- response.angle: the angle to the target
The minimum code required for a bot:
var NewBot = function() {};
NewBot.prototype = new Bot();
server.registerBotScript("NewBot");
If you want your bot to be named something different from the class name you've used, pass a second parameter to the server.registerBotScript
function:
server.registerBotScript("NewBot", "Noob");
The game engine calls each bot's setup() function at the beginning of the game.
NewBot.prototype.setup = function() {
// Do stuff here
};
And then each click, it calls the bot's run() function. This is where the bulk of the bot logic should go.
NewBot.prototype.run = function() {
return { command: 'wait', team: {} };
};
The run() function returns an object with two properties:
command
: the bot's command for this round (a string). Default commands (rulesets may add or modify commands):forward
backward
left
right
fire
mine
strafe-left
strafe-right
wait
self-destruct
team
: an object that will get sent to the other bots on the team. You can access it viathis.state.payload
.
A list of properties available under this.state
:
world
: a copy ofruleset.properties.world
. In general, there arewidth
andheight
properties that let you know how big the world is.bots
: an array of all the currently living bots.id
: bot's unique ID (integer)name
: bot's team namex
andy
: bot's locationangle
: angle the bot is pointinghealth
: the current health of the bot (0–100)
obstacles
: an array of all the obstacles. Each obstacle has the following properties:x
andy
: coordinates for the upper left corner of the obstaclewidth
: width of obstacleheight
: height of obstacle
items
: an array of all the items. Each item has the following properties:x
andy
: coordinates for the center of the itemradius
: radius of itemtype
: type, currently onlyhealth
andammo
are supported (but rulesets may add new items)
weapons
: an array of all the weapons currently in play. Each weapon has the following properties:x
andy
: weapon's locationangle
: angle the weapon is pointingowner
: ID for the bot who fired the weapontype
: string, currently onlybullet
andmine
are supported (but rulesets may add new weapons)
payload
: object passed in via theteam
property returned from the bot's run() command
Custom rulesets allow you to modify game parameters and dynamics.
Minimum code required for a custom ruleset:
var ruleset = new Ruleset(server);
ruleset.name = "customrulesetname";
// Ruleset tweaks go here
server.setRuleset(ruleset);
Anything in the ruleset is tweakable. For example, to change existing properties or add new ones:
// Tweaking an existing property
ruleset.properties.botsPerTeam = 5;
// Adding a new property
ruleset.properties.confundusCharm = 10;
To add a new command (see teleport):
// Adds "pulse" as a command available to bots
ruleset.commands.pulse = function(bot) {
// Do things
}
And since it's an HTML/CSS game, you can also include DOM changes (see demo2):
$("body").css("background", "#f00"); // Don't do this
properties
weapons
items
commands
- If a command moves a bot, it should return a position object; otherwise it need not return anything.
resetGame()
: called at the beginning of a new gameregisterBotScript(teamNum, botScript, name)
: registers a new bot script (you generally won't want to change this)generateObstacles()
: returns array of obstacles (objects withx
,y
,width
, andheight
properties)generateItems()
: returns array of items (objects withx
,y
,radius
, andtype
properties)initializeBot(bot, id)
: initialize bot (you generally won't want to change this)postInitBot(bot)
: post-init per-bot setup hooksetInitialPlacement(bot)
: setsbot.x
andbot.y
at the beginning of each gameinitializeGame()
: game init hookstartRound(clicks)
: called at the beginning of each roundresetCollisionFlags(bot)
: resets collision flagsupdateFlags(bot)
: updates bot flags and countersupdateBot(bot, pos)
: hook to allow the server to move bots (see orbit, conveyor)parseCommand(command, bot)
: parses command (you generally won't want to change this)checkCollisions(bot, newPosition)
: checks for collisionspostProcess(bot)
: called after each bot is processedendRound()
: called at the end of each roundgameOver()
: returns true or false depending on if game over conditions have been metgetWinner()
: returns name of the team who wongetHealth()
: returns array of combined health for each team
These are part of ruleset
. To add new functions, modify draw.world()
.
draw.world()
: draws everything in order (clear, backgroundLayer, health, obstacles, bots, weapons, particles, foregroundLayer)draw.clear()
: clears the canvasdraw.backgroundLayer()
: draws the background layer (default ruleset draws a grid)draw.foregroundLayer()
: draws the foreground layer (default is nothing)draw.obstacles()
: loops through obstacles and callsdraw.obstacle
for each one (you probably won't need to modify this)draw.obstacle(obstacle)
: draws an obstacledraw.items()
: loops through items and calls their callbacksdraw.bot(x, y, angle, color, radius, health)
: draws a botdraw.weapon(x, y, angle, type, owner, obj)
: draws a weapon (bullet, mine, etc.)draw.particles()
: loops through particles, runs the decay on each (TODO: move this out of drawing code), and callsdraw.particle
for each one (you probably won't need to modify this)draw.particle(particle, newPos)
: draws a particledraw.health()
: modifies the HTML elements that store the healthdraw.paused()
: draws the paused state (dark overlay, white pause icon)draw.endgame(winner)
: draws the endgame state
These are part of ruleset
.
draw.width
: if you modifyproperties.world.width
, modify this as welldraw.height
: if you modifyproperties.world.height
, modify this as welldraw.ruleset
: makes the ruleset object available to drawing codedraw.server
: makes the server object available to drawing code