On 22/02/2012 12:24 PM, darwinist wrote: [...]
You know this post wouldn't smell like some sort of scam if you didn't
use a Gmail account, used a "real name", and there weren't lots of
examples on Google already.
Andrew Poulos
As a show of good faith, here is my own meagre example. This of course
won't count as an entry into the competition.
Feel free to copy as much of it as you want if you submit your own
example.
(You can test it at
http://pagefabricator.com/gametest.html and see
that I mentioned this thread on that page. It's a very basic platform
game but you can control two sprites simultaneously.)
<!--
Public Domain 2012
-->
<body onkeydown="keydown(event)" onkeyup = "keyup(event)">
<input type="text" id="output_box" size=100></input><br>
<canvas style='border-style:solid;border-width:1px;' id="game_canvas"
width="566" height="350">
This web-browser does not implement the canvas element.<br>
Try Firefox, Chrome, Safari or Opera.
</canvas>
<br>
Money $<input type='text' style='width:50px;' id='cash' />
Required <input type='text' style='width:50px;' id='requirement' />
Health <input type='text' style='width:50px;' id='health' />
<br>
Controls:<br>
Sprite 1: up down left right<br>
Sprite 2: w s a d<br><br>
Goal: Get the required amount of money before exiting the level
through the swirl
<br>
<script>
function get_element(id)
{return document.getElementById(id);}
function clear_canvas()
{drawing_2d.clearRect(0,0, canvas.width, canvas.height);}
function clear_buffer()
{buffer_drawing.clearRect(0,0, buffer.width, buffer.height);}
function put_image(image, x, y)
{drawing_2d.drawImage(image, x, y);}
function buffer_image(image, x, y)
{if (image!=false) buffer_drawing.drawImage(image, x, y);}
function buffer_frame(image, frame_number, frame_width, put_x, put_y)
{
var src_x = frame_number*frame_width;
buffer_drawing.drawImage(image, src_x, 0, frame_width-5,
image.height, put_x, put_y, frame_width-5, image.height);
}
function run_code(code)
{eval(code);}
function enter_pressed(e)
{return (e.keyCode == 13) ? true: false;}
function keydown(e)
{
// keycodes go left, up, right down, from 37 to 40
if (e.keyCode == 37) left_pressed = true;
if (e.keyCode == 38) up_pressed = true;
if (e.keyCode == 39) right_pressed = true;
if (e.keyCode == 40) down_pressed = true;
// wasd are : 87, 65, 83, 68
else if (e.keyCode == 87) w_pressed = true;
else if (e.keyCode == 65) a_pressed = true;
else if (e.keyCode == 83) s_pressed = true;
else if (e.keyCode == 68) d_pressed = true;
}
function keyup(e)
{
// keycodes go left, up, right down, from 37 to 40
if (e.keyCode == 37) left_pressed = false;
else if (e.keyCode == 38) up_pressed = false;
else if (e.keyCode == 39) right_pressed = false;
else if (e.keyCode == 40) down_pressed = false;
// wasd are : 87, 65, 83, 68
else if (e.keyCode == 87) w_pressed = false;
else if (e.keyCode == 65) a_pressed = false;
else if (e.keyCode == 83) s_pressed = false;
else if (e.keyCode == 68) d_pressed = false;
}
function jump(sprite, height)
{
sprite.ascent_rate = height;
sprite.jumping = true;
}
function handle_block_collision(mover, target)
{
// What kind of collision is it?
// We will judge this by their previous position. If they used to be
above it, it's a
// bottom-collision. If they used to be to the right of it, it's a
left-collision, etc
// bottom collision
if (mover.bottom > target.top && mover.previous_bottom <= target.top)
{
mover.top = target.top - mover.height;
mover.bottom = mover.top + mover.height;
mover.ascent_rate = 0;
mover.grounded = true;
}
// top collision
else if (mover.top < target.bottom && mover.previous_top >=
target.bottom)
{
mover.top = target.bottom;
mover.bottom = mover.top + mover.height;
mover.ascent_rate = 0;
}
// right collision
else if (mover.right > target.left && mover.previous_right <=
target.left)
{
mover.left = target.left - (mover.width);
mover.right = mover.left + mover.width;
if (mover.ascent_rate > 0) mover.ascent_rate /=2;
if (mover.manual == true) mover.speed = 0;
else mover.direction =-1;
}
// left collision
else if (mover.left < target.right && mover.previous_left >=
target.right)
{
mover.left = target.right;
mover.right = mover.left + mover.width;
if (mover.ascent_rate > 0) mover.ascent_rate /=2;
if (mover.manual == true) mover.speed = 0;
else mover.direction = 1;
}
else
{
clearInterval(timer);
alert("collision, but don't know what kind\nprevious right was "+
mover.previous_right+ " and object left is "+target.left +
" previous bottom was " + mover.previous_bottom + " and object
top is "+target.top);
}
}
function handle_treasure_collision(mover, target)
{
if (mover.type == sprite_object)
{
target.type=destroyed_object;
target.image_type=destroyed_object;
cash += 10;
}
}
function handle_monster_collision(mover, target)
{
if (mover.type == sprite_object)
{
// bottom collision
if (mover.bottom > target.top && mover.previous_bottom <=
target.previous_top)
{
// target.type=destroyed_object;
//target.image_type=destroyed_object;
target.image_type = monster_bitten_object;
health -=10;
if (left_pressed && mover == sprite) sprite.direction =-1;
if (right_pressed && mover == sprite) sprite.direction =1;
if (a_pressed && mover == sprite2) sprite2.direction =-1;
if (d_pressed && mover == sprite2) sprite.direction =1;
jump(mover, 10);
}
// top collision
if (mover.top < target.bottom && mover.previous_top >=
target.previous_bottom)
{
health -= 10;
target.image_type = monster_bitten_object;
}
// right collision
else if (mover.right > target.left && mover.previous_right <=
target.previous_left)
{
health -= 10;
target.image_type = monster_bitten_object;
target.direction = 1;
}
// left collision
else if (mover.left < target.right && mover.previous_left >=
target.previous_right)
{
health -= 10;
target.image_type = monster_bitten_object;
target.direction = -1;
}
else // can't determine the kind
{
target.image_type = monster_bitten_object;
if (mover.grounded) health -=10;
jump(mover, 10);
}
}
}
function handle_win_collision(mover, target)
{
if (mover.type != sprite_object) return;
if (cash >= required_cash)
{
mover.type = destroyed_object;
mover.image_type = destroyed_object;
mover.finished = true;
if (sprite.finished && sprite2.finished)
{
alert("level complete");
clearInterval(timer);
current_level++;
start_level();
}
}
else
{
// What kind of collision?
mover.direction *=-1;
// bottom collision
if (mover.bottom > target.top && mover.previous_bottom <=
target.top)
{
mover.top = target.top - mover.height;
mover.bottom = mover.top + mover.height;
mover.ascent_rate = 10;
mover.speed =0;
mover.grounded = false;
}
// top collision
else if (mover.top < target.bottom && mover.previous_top >=
target.bottom)
{
mover.top = target.bottom;
mover.bottom = mover.top + mover.height;
mover.ascent_rate = 0;
}
// right collision
else if (mover.right > target.left && mover.previous_right <=
target.left)
{
mover.left = target.left - (mover.width+5);
mover.right = mover.left + mover.width;
mover.ascent_rate /=2;
mover.speed = 0;
}
// left collision
else if (mover.left < target.right && mover.previous_left >=
target.right)
{
mover.left = target.right + 5;
mover.right = mover.left + mover.width;
mover.ascent_rate /=2;
mover.speed = 0;
}
alert("not enough cash");
left_pressed = false;right_pressed = false;
a_pressed = false;d_pressed = false
}
}
function check_map_object_collisions(sprite)
{
//var collision = false;
var num_objects = map_objects.length;
for (var mover = 0; mover < num_objects; mover++)
{
// If it's a moving object, check for collisions.
if (map_objects[mover].moves && map_objects[mover].type !=
destroyed_object)
{
for (var i=0; i < num_objects; i++)
{
// If object1 moves and intersects with object2, then 's a
collision.
if ((i != mover) &&
(map_objects[mover].right > map_objects
.left) &&
(map_objects[mover].left < map_objects.right) &&
(map_objects[mover].bottom > map_objects.top) &&
(map_objects[mover].top < map_objects.bottom))
{
//alert("Collision with block "+i);
//clearInterval(timer);
var object_type = map_objects.type;
// If it intersects with a block:
if (object_type == block_object || object_type == wall_object)
handle_block_collision(map_objects[mover], map_objects, i);
// If it intersects with treasures
else if (object_type == treasure_object)
handle_treasure_collision(map_objects[mover], map_objects,
i);
// if it intersects with a monster:
else if (object_type == monster_object || object_type ==
monster_bitten_object)
handle_monster_collision(map_objects[mover], map_objects, i);
// if it intersects with the level-end:
else if (object_type == win_object)
handle_win_collision(map_objects[mover], map_objects);
}
}
}
}
}
function move_objects()
{
var num_objects = map_objects.length;
for (var i=0; i< num_objects; i++)
{
if (map_objects.moves && map_objects.type != destroyed_object)
{
// if they're running, move them and slow them down.
if (map_objects.speed > 0)
{
map_objects.left += (map_objects.speed *
map_objects.direction);
map_objects.left = Math.round(map_objects.left);
if (map_objects.manual && map_objects.grounded)
{
map_objects.speed *= 0.8;
if (map_objects.speed < 1) map_objects.speed = 0;
}
}
// Fall or rise, according to ascent_rate;
map_objects.top-=(map_objects.ascent_rate);
map_objects.ascent_rate-=gravity;
map_objects.grounded = false;
// Update their "right" and "bottom" properties.
map_objects.right = map_objects.left + map_objects.width;
map_objects.bottom = map_objects.top + map_objects.height;
}
}
}
function remember_previous_positions()
{
var num_objects = map_objects.length;
for (i = 0; i < num_objects; i++)
{
if (map_objects.moves)
{
// Remember the elements's last position.
map_objects.previous_right = map_objects.right;
map_objects.previous_left = map_objects.left;
map_objects.previous_bottom = map_objects.bottom;
map_objects.previous_top = map_objects.top;
}
}
}
function process_keyboard_controls()
{
// if not jumping, they can run, jump, etc.
if (sprite.grounded)
{
if (up_pressed) jump(sprite, jump_height);
// Test for left/right keys pressed.
if (left_pressed)
{
if (sprite.direction == 1) // going right, change direction
{
sprite.direction = -1;
sprite.speed = 2;
}
else sprite.speed +=2; // Already going left, go faster
}
if (right_pressed)
{
if (sprite.direction == -1) // going left, change direction
{
sprite.direction = 1;
sprite.speed = 2;
}
else sprite.speed +=2; // already going right, go faster
}
}
// Now the second sprite.
if (sprite2.grounded)
{
if (w_pressed) jump(sprite2, jump_height);
// Test for left/right keys pressed.
if (a_pressed)
{
if (sprite2.direction == 1) // going right, change direction
{
sprite2.direction = -1;
sprite2.speed = 2;
}
else sprite2.speed +=2; // Already going left, go faster
}
if (d_pressed)
{
if (sprite2.direction == -1) // going left, change direction
{
sprite2.direction = 1;
sprite2.speed = 2;
}
else sprite2.speed +=2; // already going right, go faster
}
}
}
function paint_frame()
{
process_keyboard_controls();
move_objects();
// Handle object-collisions according to object-type
check_map_object_collisions(sprite);
remember_previous_positions();
// Clear the image buffer and create a new frame
clear_buffer();
// Draw the blocks
var num_objects = map_objects.length;
for (var i=0; i < num_objects; i++)
buffer_image(object_images[map_objects.image_type],
map_objects.left, map_objects.top);
// draw the sprite
//buffer_image(sprite.image, sprite.left, sprite.top);
// Apply the drawing-buffer to the canvas
// Nine arguments: the element, source (x,y) coordinates, source
width and
// height (for cropping), destination (x,y) coordinates, and
destination width
// and height (resize).
// context.drawImage(img_elem, sx, sy, sw, sh, dx, dy, dw, dh);
//output.value = sprite_x_distance + ", "+ sprite_y_distance;
var sprite_x_distance = Math.abs(sprite.left-sprite2.left)
+sprite.width;
var sprite_y_distance = Math.abs(sprite.top-sprite2.top)
+sprite.height;
var min_sprite_x = Math.min(sprite.left, sprite2.left);
var min_sprite_y = Math.min(sprite.top, sprite2.top);
var sprites_x_mid_point = min_sprite_x + (sprite_x_distance/2);
var sprites_y_mid_point = min_sprite_y + (sprite_y_distance/2);
var frame_width = Math.max(canvas.width, sprite_x_distance
+200); // Source width
var frame_height = Math.max(canvas.height, sprite_y_distance+200);
// source height
var width_ratio = frame_width / canvas.width;
var height_ratio = frame_height / canvas.height;
if (width_ratio > height_ratio) frame_height =
Math.round(canvas.height * width_ratio);
else frame_width = Math.round(height_ratio * canvas.width);
var frame_x_zero = Math.max(0, (sprites_x_mid_point -
Math.max(display_x_offset, (frame_width/2)))); // source x
var frame_y_zero = Math.max(0, (sprites_y_mid_point -
Math.max(display_y_offset, (frame_height/2)))); // source y
//output.value = "height ratio: "+height_ratio + " and width ratio: "
+ width_ratio;
//output.value = "frame_height: "+frame_height + " and frame_width: "
+ frame_width;
clear_canvas();
drawing_2d.drawImage(buffer,
frame_x_zero,
frame_y_zero,
frame_width,
frame_height,
0,0, // destination x and y
canvas.width, canvas.height); // destination size
//put_image(buffer, -(sprites_x_mid_point-display_x_offset), -
(sprites_y_mid_point-display_y_offset));
// Update the text boxes
if (health <= 0)
{
alert("dead"); clearInterval(timer);
start_level();
}
cash_box.value = cash;
//points_box.value = points;
health_box.value = health;
}
// Create a monster and put it on the map
function put_monster(x, y)
{
var monster = new Object();
monster.type = monster_object;
monster.image_type = monster_object;
monster.moves = true;
monster.speed = 2;
monster.direction = -1;
monster.grounded = false;
monster.ascent_rate = 0;
monster.top = y;
monster.manual = false;
monster.left = x;
monster.width = monster_width;
monster.height = monster_height;
monster.right = monster.left + monster.width;
monster.bottom = monster.top + monster.height;
monster.previous_left = monster.left;
monster.previous_right = monster.right;
monster.previous_top = monster.top;
monster.previous_bottom = monster.bottom;
map_objects.push(monster);
}
function put_treasure(x, y)
{
var treasure = new Object();
treasure.type = treasure_object;
treasure.image_type = treasure_object;
treasure.top = y;
treasure.left = x;
treasure.right = treasure.left + treasure_width;
treasure.bottom = treasure.top + treasure_height;
map_objects.push(treasure);
}
function put_block(x, y)
{
var block = new Object();
block.top = y;
block.type = block_object;
block.image_type = block_object;
block.left = x;
block.width = block_width;
block.height = block_height;
block.right = block.left + block_width;
block.bottom = block.top + block_height;
map_objects.push(block);
}
function put_wall(x, y)
{
var wall = new Object();
wall.type = wall_object;
wall.image_type = wall_object;
wall.top = y;
wall.left = x;
wall.width = 30;
wall.height = 90;
wall.right = wall.left + wall.width;
wall.bottom = wall.top + wall.height;
map_objects.push(wall);
}
function put_win(x, y)
{
var win = new Object();
win.type = win_object;
win.image_type = win_object;
win.top = y;
win.left = x;
win.width = 30;
win.height = 30;
win.right = win.left + win.width;
win.bottom = win.top + win.height;
map_objects.push(win);
}
function start_level()
{
var map = levels[current_level].map;
var cash_required = levels[current_level].cash_required;
map_objects = new Array();
var level_length = map.length;
y = 0;
x = 0;
var block_pixels = 30;
for (var i =0; i < level_length ; i++)
{
if (map == "m") put_monster(x, y);
else if (map == "=") put_block(x, y);
else if (map == "$") put_treasure(x, y);
else if (map == ":") put_wall(x, y);
else if (map == "!") put_win(x, y);
else if (map == "1") {sprite.left = x; sprite.top = y}
else if (map == "2") {sprite2.left = x; sprite2.top = y}
if (map == "\n")
{
x = 0;
y+=30;
}
else x += block_pixels;
}
sprite.type = sprite_object; sprite.image_type = sprite_object;
sprite.speed = 0; sprite.ascent_rate = 0;
sprite2.speed = 0; sprite2.ascent_rate = 0;
sprite2.type = sprite_object; sprite2.image_type = sprite_2_object;
map_objects.push(sprite);
map_objects.push(sprite2);
buffer.width = x+200;
buffer.height = y+200;
// adjust the size of the buffer so it's the same
// proportion of the canvas' height and width
// this avoids errors when scaling.
buffer_width_ratio = buffer.width / canvas.width;
buffer_height_ratio = buffer.height / canvas.height;
if (buffer_width_ratio > buffer_height_ratio)
buffer.height = canvas.height * buffer_width_ratio;
else buffer.width = canvas.width * buffer_height_ratio;
requirement_box.value = levels[current_level].cash_required;
health = 100;
cash = level_start_cash;
up_pressed = false; down_pressed = false; left_pressed = false;
right_pressed = false;
a_pressed = false; s_pressed = false; d_pressed = false; w_pressed =
false;
timer = setInterval(paint_frame, frame_interval);
}
// debug information
var output = get_element("output_box");
// The display canvas and drawing context
var canvas = get_element("game_canvas");
var drawing_2d = canvas.getContext("2d");
// The hidden buffer to create the scene piece by piece
var buffer = document.createElement("canvas");
buffer_drawing = buffer.getContext("2d");
// How often to render the scene
var frame_rate = 30;
var frame_interval = 1000/frame_rate;
var timer; // to update the image every x milliseconds.
// output boxes:
var requirement_box = get_element("requirement");
var cash_box = get_element("cash");
var health_box = get_element("health");
// Scores
var cash = 0;
var level_start_cash = 0;
var points = 0;
var health = 100;
var required_cash = 200
// collision types (which side of the player hit the object)
var collision_right = 1;
var collision_left = 2;
var collision_top = 3;
var collision_bottom = 4;
// Some things to handle running and jumping effect
var jump_height = 15;
var gravity = 1;
var ascent_rate = 0; // how much upward momentum do they have
var grounded = false; // are they on the ground?
var running_speed = 0; // how fast moving
var direction = 1; // Which direction moving? right is 1. Left is -1;
// Key state variables
var left_pressed = false
var up_pressed = false;
var right_pressed = false;
var down_pressed = false;
// keys for the second sprite
var w_pressed = false;
var a_pressed = false;
var s_pressed = false;
var d_pressed = false;
// Map object types
var destroyed_object = 0;
var block_object = 1;
var jump_enhancer_object = 2;
var treasure_object = 3;
var health_object = 4;
var damage_object = 5;
var win_object = 6;
var monster_object = 7;
var sprite_object = 8;
var monster_bitten_object = 9;
var wall_object = 10;
var sprite_2_object = 11;
var win_object = 12;
var level = "";
// Create some map objects
var map_objects = new Array();
var object_images = new Array();
// the background-blocks image.
var block_image = new Image(); block_image.src = "block.png";
var block_width = 90; var block_height = 30;
var wall_image = new Image(); wall_image.src = "wall.png";
var treasure_image = new Image(); treasure_image.src = "treasure.png";
var treasure_height = 30;
var treasure_width = 30;
var monster_image = new Image(); monster_image.src = "monster.png";
var monster_bitten_image = new Image(); monster_bitten_image.src =
"monster_bitten.png";
var monster_height = 30; var monster_width =30;
var win_image =new Image(); win_image.src = "win.png";
var sprite_image = new Image();
sprite_image.src = "sprite1.png";
var sprite_2_image = new Image();
sprite_2_image.src = "sprite2.png";
object_images[destroyed_object] = false;
object_images[block_object] = block_image;
object_images[treasure_object] = treasure_image;
object_images[monster_object] = monster_image;
object_images[sprite_object] = sprite_image;
object_images[monster_bitten_object] = monster_bitten_image;
object_images[wall_object] = wall_image;
object_images[sprite_2_object] = sprite_2_image;
object_images[win_object] = win_image;
// The character
var sprite = new Object();
sprite.type = sprite_object;
sprite.image_type = sprite_object;
sprite.width = 19;
sprite.height = 42;
sprite.left = 50;
sprite.top = 10;
sprite.right = 0;
sprite.bottom = 0;
sprite.ascent_rate = 0;
sprite.grounded = false;
sprite.moves = true;
sprite.manual = true;
sprite.speed = 0;
sprite.direction = 1;
// Remember the sprite's last position.
sprite.previous_right = sprite.right;
sprite.previous_left = sprite.left;
sprite.previous_bottom = sprite.bottom;
sprite.previous_top = sprite.top;
map_objects.push(sprite);
// The second character
var sprite2 = new Object();
sprite2.image_type = sprite_2_object;
sprite2.type = sprite_object;
sprite2.width = 19;
sprite2.height = 42;
sprite2.left = 50;
sprite2.top = 10;
sprite2.right = 0;
sprite2.bottom = 0;
sprite2.ascent_rate = 0;
sprite2.grounded = false;
sprite2.moves = true;
sprite2.manual = true;
sprite2.speed = 0;
sprite2.direction = 1;
// Remember the sprite's last position.
sprite2.previous_right = sprite2.right;
sprite2.previous_left = sprite2.left;
sprite2.previous_bottom = sprite2.bottom;
sprite2.previous_top = sprite2.top;
map_objects.push(sprite2);
// Figure out the display offsets based on the canvas and sprite
dimensions.
var display_y_offset = (canvas.height/2) - (sprite.height/2);
var display_x_offset = (canvas.width/2) - (sprite.width/2);
var current_level = 0;
var levels = new Array();
levels[0] = new Object();
levels[0].map = ""+
":mm mm :\n"+
"| |\n"+
"|=--=--=--=--=-- |\n"+
": : :\n"+
"| 2 | 1 |\n"+
"| | |\n"+
": =--=--: =--=--:\n"+
"| $ | $$ |\n"+
"| $ | |\n"+
": $$$$ : $$$$ :\n"+
"| | |\n"+
"| | |\n"+
":=--=-- :=--=-- :\n"+
"| $$ | |\n"+
"| $$$ | $$$|\n"+
": =--=--: =--=-:\n"+
"| $$$ | $$$ :\n"+
"| $ | |\n"+
": $ | |\n"+
"| $ : !\n"+
"| $ | !\n"+
"=--=--=--=--=--==--";
levels[0].cash_required = 200;
levels[1] = new Object();
levels[1].cash_required = 400;
levels[1].map = ""+
":=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--:\n"+
"| mmmmmmmmmmmm |\n"+
"| =--=--=--=--=--=--=--=--=--=--=--=--=--=--|\n"+
": $ :\n"+
"| |\n"+
"| ==-- $ |\n"+
": =--=-- $ :\n"+
"| =--=-=-- $ ! |\n"+
"| =--=--==-- $ =--=--=--=-- =--=--=-- |\n"+
": 21 $ :\n"+
"| $ $$$$$$$$$$$$$$$$$$ |\n"+
"|=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--|";
start_level();
</script>
</body>