Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
hat
===

"Wear a Hat". Browser-based multiplayer game. Currently only tested and functioning on Google Chrome.


Why
==

This is just for fun. The point of the game is to find and hold on to the one hat that exists in the world. The only way to lose the hat is to close the window or stay idle for some time. Press enter to open the chat prompt.

Instructions
==

1. Get the files
2. "python ./loop.py"
3. Play with people on your local network (your_ip_address:8000)
3 changes: 2 additions & 1 deletion game.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ def __init__(self, session_id):
self.position = Position(0, 0)
self.movement = Movement(0, 0)
self.character = choice(self.guy_types)
self.speech = None;

def move(self, x, y, dx, dy):
self.position.update(x, y)
self.movement.update(dx, dy)

def dictify(self):
return {'id': self.id, 'position': {'x': self.position.x, 'y': self.position.y}, 'character': self.character, 'movement': {'dx': self.movement.dx, 'dy': self.movement.dy}}
return {'id': self.id, 'position': {'x': self.position.x, 'y': self.position.y}, 'character': self.character, 'movement': {'dx': self.movement.dx, 'dy': self.movement.dy}, 'speech': self.speech}

class Hat(object):
def __init__(self):
Expand Down
10 changes: 9 additions & 1 deletion messenger.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,25 @@ def on_open(self, info):
def on_message(self, text):
message = json.loads(text)
if message['action'] == 'move':
player = message['body']['session']
try:
player = message['body']['session']
except KeyError:
self.debug()
self.send_obj('ack', {})
return

x = message['body']['x']
y = message['body']['y']
dx = message['body']['dx']
dy = message['body']['dy']
hat_owner = 0
speech = message['body']['speech']
if message['body'].has_key('hat_owner'):
hat_owner = int(message['body']['hat_owner'])

self.game_state.players[player].position.update(x, y)
self.game_state.players[player].movement.update(dx, dy)
self.game_state.players[player].speech = speech;
if hat_owner:
try:
self.game_state.assign_hat(player);
Expand Down
209 changes: 159 additions & 50 deletions static/scripts/animations.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function Hat(owner, xpos, ypos) {
this.owner = owner;
this.xpos = xpos;
this.ypos = ypos;
this.message = null;

this.get_image = function( tile_num ) {
return $('#Hat_pic');
Expand All @@ -74,6 +75,10 @@ function Hat(owner, xpos, ypos) {
this.owner = owner;
}
}

this.get_message = function() {
return this.message;
}
}

function dude(player_id, xpos, ypos, dx, dy, move_speed, has_hat, guy) {
Expand All @@ -86,6 +91,7 @@ function dude(player_id, xpos, ypos, dx, dy, move_speed, has_hat, guy) {
this.move_speed = move_speed;
this.has_hat = has_hat;
this.guy = guy;
this.message = null;

// Methods
this.get_image = function( tile_num ) {
Expand Down Expand Up @@ -156,40 +162,13 @@ function dude(player_id, xpos, ypos, dx, dy, move_speed, has_hat, guy) {
return this.guy;
}

/*
talk = function( ctx, width, height, text ) {
var x = xpos + dude_size + 5;
var y = ypos - 5;

var curvy_width = 20;
var curvy_height = 20;
var curviness = 10;
this.get_message = function() {
return this.message;
}

// Draw curvy part
ctx.beginPath();
ctx.moveTo(x, y);
ctx.quadraticCurveTo(x+curvy_width/2+curviness, y-curvy_height/2, x, y-curvy_height);
ctx.moveTo(x, y);
ctx.quadraticCurveTo(x+curvy_width/2+curviness, y-curvy_height/2, x+curvy_height, y-curvy_height);

//Draw Rectangular part
var rect_x = x + curvy_width/2 - width/2;
var rect_y = y - curvy_height - height;

ctx.moveTo(rect_x, rect_y+radius);
ctx.lineTo(rect_x, rect_y+height-radius);
ctx.quadraticCurveTo(rect_x, rect_y+height, rect_x+radius, rect_y+height);
ctx.lineTo(rect_x+width/2-curvy_width/2, rect_y+height);
ctx.moveTo(rect_x+width/2+curvy_width/2, rect_y+height);
ctx.lineTo(rect_x+width-radius, rect_y+height);
ctx.quadraticCurveTo(rect_x+width, rect_y+height, rect_x+width, rect_y+height-radius);
ctx.lineTo(rect_x+width, rect_y+radius);
ctx.quadraticCurveTo(rect_x+width, rect_y, rect_x+width-radius, rect_y);
ctx.lineTo(rect_x+radius, rect_y);
ctx.quadraticCurveTo(rect_x, rect_y, rect_x, rect_y+radius);
ctx.stroke();
}
*/
this.set_message = function(message) {
this.message = message;
}


}
Expand All @@ -207,6 +186,10 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {
this.dy = 0;
this.move_speed = move_speed;
this.other_dudes = {};
this.messageTimeout = 500;
this.messageCounter = 0;
this.idleTimeout = 1000;
this.idleTimer = 0;

var that = this;
this.network = null
Expand Down Expand Up @@ -267,12 +250,25 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {
this.update_hat();

// Send information
var json_message = JSON.stringify({'action': 'move', 'body': {'session': window.session_id, 'x': this.xpos, 'y': this.ypos, 'dx': this.dx, 'dy': this.dy, 'hat_owner': this.your_dude.get_hat_status()}});
var json_message = JSON.stringify({'action': 'move', 'body': {'session': window.session_id, 'x': this.xpos, 'y': this.ypos, 'dx': this.dx, 'dy': this.dy, 'hat_owner': this.your_dude.get_hat_status(), 'speech': this.your_dude.get_message()}});
if(this.network !== null) {
//console.log(json_message);
this.network.send(json_message);
}

if( this.your_dude.get_message() != null && this.messageCounter < this.messageTimeout) {
this.messageCounter++;
}
else if( this.messageCounter >= this.messageTimeout ) {
this.messageCounter = 0;
this.your_dude.set_message(null);
}

this.idleTimer++;
if ( this.idleTimer >= this.idleTimeout ) {
location.reload(true);
}

// Draw player
this.draw_object(this.your_dude);

Expand Down Expand Up @@ -305,18 +301,10 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {
this.hat.set_owner(window.session_id);
this.your_dude.set_hat_status(1);
}
else {
this.draw_object(this.hat);
}
}
else if ( this.hat.get_owner() != window.session_id ){
this.your_dude.set_hat_status(0);
}
else {
this.hat.set_position(this.your_dude.get_position()[0], this.your_dude.get_position()[1]);
}

if( !this.hat.get_owner() ) {
this.draw_object(this.hat);
}

}

this.update_dude = function(dude, xpos, ypos, dx, dy, has_hat, guy) {
Expand All @@ -328,11 +316,17 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {
return dude;
}

this.add_message = function(message) {
this.messageCounter = 0;
this.your_dude.set_message(message);
};

this.draw_object = function(object) {
var image_jq, img, img_height, img_width, obj_x, obj_y, x_off, x_off_other, y_off, y_off_other;
var image_jq, img, img_height, img_width, obj_x, obj_y, x_off, x_off_other, y_off, y_off_other, message;
var draw_locations = new Array();
obj_x = object.get_position()[0];
obj_y = object.get_position()[1];
message = object.get_message();

if( false ) {
console.log([object.get_position()[0], object.get_position()[1], this.xpos, this.ypos]);
Expand Down Expand Up @@ -387,6 +381,59 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {

for( var i=0; i<draw_locations.length; i++ ) {
this.context.drawImage(img, draw_locations[i][0], draw_locations[i][1], img_width, img_height);
if( message != null && message != '' ) {
// Speech bubble
var x = draw_locations[i][0] + img_width;
var y = draw_locations[i][1] + 20;

var curvy_width = 20;
var curvy_height = 20;
var curviness = 10;
var width = 150;
var height = 90;
var radius = 10;

var rect_x = x + curvy_width/2 - width/2;
var rect_y = y - curvy_height - height;

// Draw curvy part
this.context.beginPath();
this.context.moveTo(x, y-curvy_height);
this.context.quadraticCurveTo(x+curvy_width/2+curviness, y-curvy_height/2, x, y);
this.context.quadraticCurveTo(x+curvy_width/2+curviness, y-curvy_height/2, x+curvy_height, y-curvy_height);

// Draw Rectangular part
this.context.lineTo(rect_x+width-radius, rect_y+height);
this.context.quadraticCurveTo(rect_x+width, rect_y+height, rect_x+width, rect_y+height-radius);
this.context.lineTo(rect_x+width, rect_y+radius);
this.context.quadraticCurveTo(rect_x+width, rect_y, rect_x+width-radius, rect_y);
this.context.lineTo(rect_x+radius, rect_y);
this.context.quadraticCurveTo(rect_x, rect_y, rect_x, rect_y+radius);
this.context.lineTo(rect_x, rect_y+height-radius);
this.context.quadraticCurveTo(rect_x, rect_y+height, rect_x+radius, rect_y+height);
this.context.lineTo(rect_x+width/2-curvy_width/2, rect_y+height);

this.context.closePath();
this.context.fillStyle = "#FFF";
this.context.fill();
this.context.stroke();

this.context.fillStyle = "#000";
this.context.font = "normal 10pt Calibri";

var letters = message.split('');
var fragment = letters[0];
var line = 0;
for(var i=1; i<letters.length; i++) {
fragment = fragment+letters[i];
if( i % 20 == 0 ) {
this.context.fillText(fragment, rect_x+10, rect_y+15+line*12);
fragment = "";
line++;
}
}
this.context.fillText(fragment, rect_x+10, rect_y+15+line*12);
}
}
}

Expand All @@ -407,25 +454,43 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {
// Down
this.dy = this.move_speed;
}

if( this.dx != 0 && this.dy != 0 ) {
this.dx = this.dx > 0 ? this.move_speed / 2 : -this.move_speed / 2;
this.dy = this.dy > 0 ? this.move_speed / 2 : -this.move_speed / 2;
}

this.idleTimer = 0;

}

this.move_stop = function( keyCode ) {
if( keyCode == 37 && this.dx == -this.move_speed ) {
if( keyCode == 37 && this.dx < 0 ) {
// Left
this.dx = 0;
}
else if( keyCode == 38 && this.dy == -this.move_speed ) {
else if( keyCode == 38 && this.dy < 0 ) {
// Up
this.dy = 0;
}
else if( keyCode == 39 && this.dx == this.move_speed ) {
else if( keyCode == 39 && this.dx > 0 ) {
// Right
this.dx = 0;
}
else if( keyCode == 40 && this.dy == this.move_speed ) {
else if( keyCode == 40 && this.dy > 0 ) {
// Down
this.dy = 0;
}

if( this.dx != 0 && this.dy == 0 ) {
this.dx = this.dx > 0 ? this.move_speed : -this.move_speed ;
}
if( this.dy != 0 && this.dx == 0 ) {
this.dy = this.dy > 0 ? this.move_speed : -this.move_speed ;
}

this.idleTimer = 0;

}

this.change_speed = function( speed ) {
Expand Down Expand Up @@ -764,3 +829,47 @@ function gameCanvas(jq_elem, xpos, ypos, move_speed, max_x, max_y) {
cancelAnimFrame(this.anim_frame);
}
}

function speech(character_limit) {
this.listening = false;
this.character_limit = character_limit;

this.handle = function(code) {
if( code == 13 ) {
this.trigger();
return true;
}

}

this.trigger = function() {
// Toggle listening
this.listening = !this.listening;

// Start listening to keyboard input
if( this.listening ) {
this.display_prompt();
$('#speech_prompt_form').find('input[type="text"]').focus();
}
else {
this.remove_prompt();
}
return true;
}

this.display_prompt = function() {
var prompt = '' +
'<div id="speech_prompt" style="background-color: #000; opacity: 0.6; z-index: 1000; top: 70%; width: 100%; height: 50px; position: absolute;">' +
'<form action="." id="speech_prompt_form" style="opacity: 1; z-index: 2000; position: relative; top: 20%;">' +
'<input type="text" maxlength="'+this.character_limit.toString()+'" style="position: relative; left: 2%; width: 90%;"></input>' +
'<input type="submit" style="display: none;"></submit>' +
'</form></div>';

$('body').append(prompt);
}

this.remove_prompt = function() {
$('#speech_prompt').remove();
return true;
}
}
7 changes: 5 additions & 2 deletions static/scripts/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,26 @@ function Networking(game) {
// update positions of existing players
$.each(state.players, function(session, player) {
if(session != window.session_id) {
var has_hat = 0 | (hat_owner == session);
var has_hat = (hat_owner == session);
if(session in that.game.other_dudes && that.game.other_dudes[session]) {
that.game.update_dude(that.game.other_dudes[session], player.position.x, player.position.y, player.movement.dx, player.movement.dy, has_hat, player.character);
that.game.other_dudes[session].set_message(player.speech);
} else {
that.game.other_dudes[session] = new dude(session, 0, 0, 0, 0, that.game.move_speed, 0, player.character);
console.log('Added player ' + session);
}
}
else {
that.game.update_dude(that.game.your_dude, player.position.x, player.position.y, player.movement.dx, player.movement.dy, that.game.your_dude.get_hat_status(), player.character);
//that.game.update_dude(that.game.your_dude, player.position.x, player.position.y, player.movement.dx, player.movement.dy, that.game.your_dude.get_hat_status(), player.character);
//that.game.your_dude.set_message(player.speech);
}
});

// delete players that left
$.each(that.game.other_dudes, function(session, player) {
if(!(session in state.players)) {
if( hat_owner == session ) {
that.game.hat.set_position(that.game.other_dudes[session].get_position()[0], that.game.other_dudes[session].get_position()[1]);
that.game.hat.set_owner(0);
}
delete that.game.other_dudes[session];
Expand Down
Loading