<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta charset="utf-8" />
<title>Reset</title>
-->
<style>
body {
background-color: black;
margin: 0;
padding: 0;
}
#assets { display: none; }
#canvasDiv { text-align: center; }
canvas { cursor: none; }
table {
margin: 0 auto;
color: #E1E1E1;
background-color: #732222;
height: 24px;
width: 800px;
border: none;
}
button { font-size: 1em; }
#buttonsArea {
color: #E1E1E1;
background-color: #732222;
width: 600px;
margin: 0 auto;
border: none;
}
</style>
</head>
<body>
<div>
<table>
<tr>
<td style="width: 18%"> totalScore </td>
<td id="totalScore" style="width: 5%"></td>
<td style="width: 18%"> oops! </td>
<td id="oopsScore" style="width: 5%"></td>
<td style="width: 18%"> goodHits </td>
<td id="goodHits" style="width: 5%"></td>
<td style="width:18%"> totalShots </td>
<td id="totalShots" style="width: 5%"></td>
</tr>
</table>
</div>
<!-- <div id="canvasDiv">
<canvas id="canvas" width="600" height="400" style="background-color:#992D2D"></canvas>
</div>
-->
<div align="center">
<table style="text-align: left; width: 100%;" border="0"
cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="width:70%";><p id="traceMsg">traceLog goes here:</p>
</td>
<td style="width:30%";> <canvas id="canvas" width="600" height="400"></canvas>
</td>
</tr>
</tbody>
</table>
</div>
<div id="buttonsArea">
<button id="pause">Pause</button>
<button id="play">Play</button>
<button id="left">Move left</button>
<button id="throw">Throw</button>
<button id="right">Move right</button>
</div>
<!-- </div> -->
<div id="assets">
<img id="lie02" src="sprites/lies02.png">
<img id="tru02" src="sprites/tru02.png">
<img id="cowpie" src="sprites/cowpie.png">
<img id="thrower" src="sprites/thrower.png">
<img id="bgCompound" src="sprites/bgCompound.jpeg">
<img id="manufacturer" src="sprites/manufacturer.png">
</div>
<script>
//debugger;
/* explain
Difference between Function constructor and function declaration
Functions created with the Function constructor do not create closures to their creation contexts;
they always are created in the global scope.
When running them, they will only be able to access their own local variables and global ones,
not the ones from the scope in which the Function constructor was called.
This is different from using eval with code for a function expression.
//function declaration
function foo() {}
Declared functions are not executed immediately. They are "saved for later use",
and will be executed later, when they are invoked (called upon).
Semicolons are used to separate executable JavaScript statements.
Since a function declaration is not an executable statement,
it is not common to end it with a semicolon.
All it can do is create an object variable parented by its current scope.
In contrast a Function Expression (by definition) is part of a larger construct.
If you want to create an anonymous function or assign a function to a prototype
or as a property of some other object you need a Function Expression.
// function expression
(function bar() {})
// function expression
x = function hello() {}
if (x) {
// function expression
function world() {}
}
// function declaration
function a() {
// function declaration
function b() {}
if (0) {
// function expression
function c() {}
}
}
*/
/***********/
/** Logic **/
/***********/
/* Initialize the game object */
function writeTraceLog(oneTraceLine){
traceCount ++;
document.getElementById("traceMsg").innerHTML += ( "<br> " + oneTraceLine);
}
var gameLoopDraw = 0; var TargetSelfDraw = 0;
var targetsLengthVar = 0; // targetsLengthVar = targets.length ;
var traceCount = 1;
var canvas = document.getElementById("canvas");
var game = new Game(canvas);
// Sounds
game.sounds.splat = new Audio("sounds/CowMooSplat.mp3");
game.sounds.goodbye = new Audio("sounds/GoodBye-Female.mp3");
game.sounds.cheering = new Audio("sounds/cheeringCrowd.mp3");
game.sounds.oops = new Audio("sounds/oops.mp3");
// Sprites
game.sprites.background = document.getElementById("bgCompound");
game.sprites.manufacturer = document.getElementById("manufacturer");
game.sprites.cowpie = document.getElementById("cowpie");
// Scores explain
//points to an element on the page. game.scores.totalScore just tells the
//program in which HTML element the score should be written.
game.scores.totalScore = document.getElementById("totalScore");
game.scores.oops = document.getElementById("oopsScore");
game.scores.hits = document.getElementById("goodHits");
game.scores.totalShots = document.getElementById("totalShots");
// Create thrower
var throwerSprite = document.getElementById("thrower");
var throwerX = canvas.width / 2; // Center of the canvas
var throwerY = canvas.height - throwerSprite.height; // Bottom of the canvas
var thrower = new Thrower(throwerSprite, throwerX, throwerY);
thrower.speed = 120 / 1000; // 120 pixels per second
thrower.cowpieSpeed = 180 / 1000; // 180 pixels per second
game.setThrower(thrower);
// Create targets
var hillarytrue = document.getElementById("tru02");
var hillarylies = document.getElementById("lie02");
var target1 = new Target(hillarylies, hillarytrue, 128, 24);
target1.speed = 120 / 1000; // 120 pixels per second
var target2 = new Target(hillarylies, hillarytrue, 0, 68);
target2.speed = 120 / 1000; // 120 pixels per second
game.addTarget(target1);
game.addTarget(target2);
/* Set event handlers */
// Pause/Resume
document.getElementById("pause").addEventListener("click", game.pause, false);
document.getElementById("play").addEventListener("click", game.resume, false);
// Actions
document.getElementById("left").addEventListener("mousedown", thrower.pressLeft, false);
document.getElementById("left").addEventListener("mouseup", thrower.releaseLeft, false);
document.getElementById("right").addEventListener("mousedown", thrower.pressRight, false);
document.getElementById("right").addEventListener("mouseup", thrower.releaseRight, false);
document.getElementById("throw").addEventListener("click", thrower.throwCowpie, false);
document.addEventListener("keydown", keyPressed, false);
document.addEventListener("keyup", keyReleased, false);
var canFire = true;
function keyPressed(e) {
writeTraceLog("function keyPressed targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
switch(e.keyCode) {
case 39: case 68: // Right arrow and D
thrower.pressRight();
break;
case 37: case 65: // Left arrow and A
thrower.pressLeft();
break;
case 38: case 87: // Up arrow and W
if(canFire) {
canFire = false;
thrower.throwCowpie();
}
break;
}
}
function keyReleased(e) {
writeTraceLog("function keyReleased(e) targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
switch(e.keyCode) {
case 39: case 68: // Right arrow and D
thrower.releaseRight();
break;
case 37: case 65: // Left arrow and A
thrower.releaseLeft();
break;
case 38: case 87: // Up arrow and W
canFire = true;
break;
}
}
/* Begin the game */
window.addEventListener("load", game.start, false);
/*************/
/** Objects **/
/*************/
/** Game **/
function GameĀ© { // function declaration
var self = this;
/** Properties **/
// Canvas
var canvas = c;
var context = canvas.getContext("2d");
// HTML elements explain
/* Objects are variables too. But objects can contain many values.
JavaScript objects are containers for named values called properties or methods.
self.sprites is an object. It's in the Javascript tutorial:
Objects are used to organize data.
self is also an object. .sprites is a property of self that also contains an object.
You cannot use var to set properties.
Objects can contain other objects and arrays as properties.
var a = {}; // This is an object
a.b = { // Property "b" is an object that contains a property "c" which is also an object
c : {}
};
a.b.c.d = "Value"; // Object "c" has a property called "d" with a string as its value.
*/
self.reset = function () {
totalScore = 0;
totalShots = 0;
oops = 0;
hits = 0;
for (var i = targets.length - 1; i >= 0; i--) {
targetsLengthVar = targets.length ;
targets.splice(index, 1);
writeTraceLog("self.reset targets.splice func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
}
for (var i = cowpies.length - 1; i >= 0; i--) {
cowpies.splice(index, 1);
writeTraceLog("self.reset cowpies.splice func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
}
}; // self.reset = function ()
self.sprites = {
background : null,
manufacturer : null,
cowpie : null
};
self.sounds = {
splat : null,
goodbye : null,
cheering : null,
oops : null
};
self.scores = {
totalScore : null,
oops : null,
hits : null,
totalShots : null
};
// Movable objects
var thrower = null;
var targets = [];
var cowpies = [];
self.setThrower = function(t) { thrower = t; thrower.game = self;
writeTraceLog("self.addThrower func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
};
self.addTarget = function(t) { targets.push(t);
writeTraceLog("self.addTarget func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount + " which target = " + t.name);
};
// States
var paused = false;
// Counters
var totalScore = 0;
var totalShots = 0;
var oops = 0;
var hits = 0;
/** Methods **/
// explain Methods are functions stored as object properties.
// http://www.w3schools.com/js/js_object_methods.asp
// Start the game ===========================
self.start = function () {
// Reset counters
totalScore = 0;
totalShots = 0;
oops = 0;
hits = 0;
writeTraceLog("self.start = function targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
// Play a sound
console.log(self.sounds.cheering);
self.sounds.cheering.play();
// Begin the game loop
requestAnimationFrame(gameLoop);
} // self.start = function () ========================
// Pause the game
self.pause = function() { paused = true; lastTimestamp = 0;
writeTraceLog("self.pause func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
};
self.resume = function() { paused = false; };
// Create a cowpie
self.createCowpie = function(x, y) {
writeTraceLog("self.createCowpie func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
var cowpie = new Cowpie(self.sprites.cowpie, x, y);
cowpie.game = this;
cowpies.push(cowpie);
};
// Remove a cowpie by its index
self.destroyCowpie = function(index) {
if(index instanceof Cowpie) {
writeTraceLog("self.destroyCowpie func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
var found = false;
numCowpies = cowpies.length;
for(var i = 0; i < numCowpies && !found; i++) {
if(cowpies == index) {
found = true;
cowpies.splice(index, 1);
}
}
} else {
cowpies.splice(index, 1);
}
} // self.destroyCowpie = function(index)
/** Private methods **/
// Collision detection
// Detect rectangular collision
var hitTest = function(a, {
return a.x <= b.x + b.width &&
a.x + a.width >= b.x &&
a.y <= b.y + b.height &&
a.y + a.height >= b.y;
}
var lastTimestamp = 0;
var gameLoop = function(timestamp) { // =================== gameLoop ==============
var i, j, numTargets, numCowpies, collision;
/* If the game is paused then do nothing */
if(paused) {
requestAnimationFrame(gameLoop);
return;
}
/* Calculate delta time */
if(lastTimestamp == 0) {
lastTimestamp = timestamp;
}
deltaTime = timestamp - lastTimestamp;
lastTimestamp = timestamp;
/* Update all objects */
// Thrower
thrower.update(deltaTime, canvas);
// Targets
numTargets = targets.length;
targetsLengthVar = targets.length;
for(i = 0; i < numTargets; i++) {
targets.update(deltaTime, canvas);
}
// Cowpies
for(i = 0; i < cowpies.length; i++) {
cowpies.update(deltaTime, canvas);
}
/* Calculate interations between all objects */
// For each cowpie calculate collision with the targets
var target;
for(i = 0; i < cowpies.length; i++) {
for(j = 0; j < numTargets; j++) {
collision = hitTest(cowpies, targets[j]);
// If a collision occurred, destroy the cowpie and change the target
if(collision) {
// Destroy cowpie
self.destroyCowpie(i);
// Change target's state and update scores
target = targets[j];
if(target.isGood()) {
self.sounds.oops.play();
oops++;
target.setGood(false);
} else {
self.sounds.splat.play();
hits++;
target.setGood(true);
}
totalScore = hits * 4 - oops * 2;
i--; // (Accounts for the cowpie being removed from the array)
break;
} // if(collision)
} // for(j = 0; j < numTargets; j++)
} // for(i = 0; i < cowpies.length; i++)
/* Display everything */
// Clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// Draw background images
context.drawImage(self.sprites.background, 0, canvas.height - 195);
context.drawImage(self.sprites.manufacturer, canvas.width - 180, canvas.height - 104);
// Draw thrower
thrower.draw(context);
// Draw targets
for(i = 0; i < numTargets; i++) { // TargetSelfDraw gameLoopDraw
if (TargetSelfDraw < 5) { gameLoopDraw ++;
writeTraceLog("if gameLoopSelf < 5 = "+ gameLoopDraw + " traceCount = " + traceCount);
}
targets.draw(context);
}
// Draw cowpies
numCowpies = cowpies.length; // Update this to account for destroyed cowpies
for(i = 0; i < numCowpies; i++) {
cowpies.draw(context);
}
// Update scores
self.scores.totalScore.innerHTML = totalScore;
self.scores.totalShots.innerHTML = totalShots;
self.scores.oops.innerHTML = oops;
self.scores.hits.innerHTML = hits;
// Start a new game loop
requestAnimationFrame(gameLoop);
} // var gameLoop = function(timestamp)
}; // EndOf function GameĀ©
/** Thrower **/
function Thrower(s, startX, startY) { // Declared functions are not executed immediately.
// They are "saved for later use", and will be executed later, when they are invoked (called upon).
var self = this;
var sprite = s;
self.x = startX;
self.y = startY;
self.width = sprite.width;
self.height = sprite.height;
self.game = null;
self.speed = 120 / 1000;
var left = 0;
var right = 0;
// For movement
self.pressLeft = function() { left = 1;
writeTraceLog("self.pressLeft func self.x = "+ self.x + " traceCount = " + traceCount);
};
self.releaseLeft = function() { left = 0; };
self.pressRight = function() { right = 1;
writeTraceLog("self.pressRight func self.x = "+ self.x + " traceCount = " + traceCount);
};
self.releaseRight = function() { right = 0; };
// Throw a cowpie
self.throwCowpie = function() {
writeTraceLog("self.throwCowpie func targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
game.createCowpie(self.x, self.y);
}
// Update position
self.update = function(deltaTime, canvas) {
var direction = right - left;
self.x += direction * self.speed * deltaTime;
if(self.x + self.width > canvas.width) {
self.x = canvas.width - self.width;
}
if(self.x < 0) {
self.x = 0;
}
}
// Draw
self.draw = function(context) {
context.drawImage(sprite, self.x, self.y, self.width, self.height);
}
} // function Thrower(s, startX, startY)
/** Cowpie **/
function Cowpie(s, startX, startY) {
var self = this;
var sprite = s;
self.x = startX;
self.y = startY;
self.width = sprite.width;
self.height = sprite.height;
self.game = null;
self.speed = 180 / 1000;
self.update = function(deltaTime, canvas) {
self.y -= self.speed * deltaTime;
if(self.y < 0) {
game.destroyCowpie(self);
}
}
self.draw = function(context) {
context.drawImage(sprite, self.x, self.y, self.width, self.height);
//writeTraceLog("self.draw cowpie targetsLengthVar = "+ targetsLengthVar + " traceCount = " + traceCount);
}
} // function Cowpie(s, startX, startY)
/** Target **/
function Target(bad, good, startX, startY) {
var self = this;
/* Properties */
self.x = startX;
self.y = startY;
self.width = bad.width;
self.height = bad.height;
self.speed = 120 / 1000;
// For changing sprite
var isGood = false;
var spriteGood = good;
var spriteBad = bad;
var sprite = spriteBad;
// For motion
var direction = 1;
var trips = 0;
var maxTrips = 2;
/* Get or set the isGood value */
self.isGood = function() {
return isGood;
}
self.setGood = function(value) {
isGood = value;
trips = 0; // Reset trips
if(isGood) {
width = spriteGood.width;
height = spriteGood.height;
} else {
width = spriteBad.width;
height = spriteBad.height;
}
}
/* Update method, called on each frame */
self.update = function(deltaTime, canvas) { // target
/* Update position */
self.x += direction * self.speed * deltaTime;
/* Check boundaries */
var hitBoundary = false;
// Check if we hit the left boundary
if(self.x < 0) {
self.x = 0;
direction = -direction;
hitBoundary = true;
}
// Check if we hit the right boundary
if(self.x + self.width > canvas.width) {
self.x = canvas.width - self.width;
direction = -direction;
hitBoundary = true;
}
// If we hit a boundary then count trips
if(hitBoundary) {
trips++;
// Switch sprites if we hit a boundary too many times
if(trips > maxTrips) {
isGood = !isGood;
if(isGood) {
width = spriteGood.width;
height = spriteGood.height;
} else {
width = spriteBad.width;
height = spriteBad.height;
}
}
}
}
/* Draw the sprite */
self.draw = function(context) {
TargetSelfDraw ++;
sprite = isGood ? spriteGood : spriteBad;
context.drawImage(sprite, self.x, self.y, self.width, self.height); //gameLoopDraw TargetSelfDraw = 0;
if (TargetSelfDraw < 5) {
writeTraceLog("if TargetSelfDra < 5 = "+ TargetSelfDraw + " traceCount = " + traceCount);
}
} // TargetSelfDraw
} // function Target(bad, good, startX, startY)
//
/*
function writeTraceLog(oneTraceLine){
document.getElementById("traceMsg").innerHTML += ( "<br> " + oneTraceLine);
}
*/
</script>
</body>
</html>