I've been working on a simple matching puzzle game for a little while now. Currently I have been able to have a countdown time and the number of matching tiles displayed as a text and I'm trying to create one for the best time completed (basically how fast the person completed the puzzle). However whenever I try to create it the text never displays.I noticed while writing the code that if I where to place the variable "txt" followed by a "." the autocomplete box will appear with .text as an available option so I would get "txt.text". I do not however get that option when writing the bestTimeTxt variable which is what I am using to display the time. I'm not sure what I have done wrong, here is my code.
<!DOCTYPE html>
<html>
<head>
<title>Recipe: Drawing a square</title>
<script src="easel.js"></script>
<script type="text/javascript">
var canvas;
var stage;
var squareSide = 70;
var squareOutline = 5;
var max_rgb_color_value = 255;
var gray = Graphics.getRGB(20, 20, 20);
var placementArray = [];
var tileClicked;
var timeAllowable;
var totalMatchesPossible;
var matchesFound;
var txt;
var bestTime;
var bestTimeTxt;
var matchesFoundText;
var squares;
function init() {
var rows = 5;
var columns = 6;
var squarePadding = 10;
canvas = document.getElementById('myCanvas');
stage = new Stage(canvas);
var numberOfTiles = rows*columns;
matchesFound = 0;
timeAllowable = 5;
bestTime = 0
txt = new Text(timeAllowable, "30px Monospace", "#000");
txt.textBaseline = "top"; // draw text relative to the top of the em box.
txt.x = 500;
txt.y = 0;
bestTimeTxt = new Text(bestTime, "30px Monospace", "#000");
bestTimeTxt.textBaseLine = "top";
bestTimeTxt.x = 300;
bestTimeTxt.y = 0;
stage.addChild(txt);
stage.addChild(bestTimeTxt);
squares = [];
totalMatchesPossible = numberOfTiles/2;
Ticker.init();
Ticker.addListener(window);
Ticker.setPaused(false);
matchesFoundText = new Text("Pairs Found: "+matchesFound+"/"+totalMatchesPossible, "30px Monospace", "#000");
matchesFoundText.textBaseline = "top"; // draw text relative to the top of the em box.
matchesFoundText.x = 500;
matchesFoundText.y = 40;
stage.addChild(matchesFoundText);
setPlacementArray(numberOfTiles);
for(var i=0;i<numberOfTiles;i++){
var placement = getRandomPlacement(placementArray);
if (i % 2 === 0){
var color = randomColor();
}
var square = drawSquare(gray);
square.color = color;
square.x = (squareSide+squarePadding) * (placement % columns);
square.y = (squareSide+squarePadding) * Math.floor(placement / columns);
squares.push(square);
stage.addChild(square);
square.cache(0, 0, squareSide + squarePadding, squareSide + squarePadding);
square.onPress = handleOnPress;
stage.update();
};
}
function drawSquare(color) {
var shape = new Shape();
var graphics = shape.graphics;
graphics.setStrokeStyle(squareOutline);
graphics.beginStroke(gray);
graphics.beginFill(color);
graphics.rect(squareOutline, squareOutline, squareSide, squareSide);
return shape;
}
function randomColor(){
var color = Math.floor(Math.random()*255);
var color2 = Math.floor(Math.random()*255);
var color3 = Math.floor(Math.random()*255);
return Graphics.getRGB(color, color2, color3)
}
function setPlacementArray(numberOfTiles){
for(var i = 0;i< numberOfTiles;i++){
placementArray.push(i);
}
}
function getRandomPlacement(placementArray){
randomNumber = Math.floor(Math.random()*placementArray.length);
return placementArray.splice(randomNumber, 1)[0];
}
function handleOnPress(event){
var tile = event.target;
tile.graphics.beginFill(tile.color).rect(squareOutline, squareOutline, squareSide, squareSide);
if(!!tileClicked === false || tileClicked === tile){
tileClicked = tile;
tileClicked.updateCache("source-overlay");
}else{
if(tileClicked.color === tile.color && tileClicked !== tile){
tileClicked.visible = false;
tile.visible = false;
matchesFound++;
matchesFoundText.text = "Pairs Found: "+matchesFound+"/"+totalMatchesPossible;
if (matchesFound===totalMatchesPossible){
gameOver(true);
}
}else{
tileClicked.graphics.beginFill(gray).rect(squareOutline, squareOutline, squareSide, squareSide);
}
tileClicked.updateCache("source-overlay");
tile.updateCache("source-overlay");
tileClicked = tile;
}
stage.update();
}
function tick() {
secondsLeft = Math.floor((timeAllowable-Ticker.getTime()/1000));
txt.text = secondsLeft;
bestTimeTxt.text = "test";
if (secondsLeft <= 0){
gameOver(false);
}
stage.update();
}
function gameOver(win){
Ticker.setPaused(true);
for(var i=0;i<squares.length;i++){
squares[i].graphics.beginFill(squares[i].color).rect(5, 5, 70, 70);
squares[i].onPress = null;
if (win === false){
squares[i].uncache();
}
}
var replayParagraph = document.getElementById("replay");
replayParagraph.innerHTML = "<a href='#' onClick='history.go(0);'>Play Again?</a>";
if (win === true){
matchesFoundText.text = "You win!"
}else{
txt.text = secondsLeft + "... Game Over";
}
}
function replay(){
init();
}
</script>
</head>
<body onload="init()">
<header id="header">
<p id="replay"></p>
</header>
<canvas id="myCanvas" width="960" height="400"></canvas>
</body>
</html>
Apparently the issue I was having was that the x and y position of the text was causing it to appear behind everything else.
Related
I have a collection of data representing cloud height measurements every minute. As new data arrives, i want to add them on the right side of the canvas, moving the older data to the left. Is it possible to do this without using a specific charting library like canvasjs?
Some additional info to make things a little bit clearer. If the webpage is opened, data of the last 180 minutes are queried by an Ajax call. The data is in json format.
<style>
canvas {
background-color: #ffffff;
}
</style>
<fieldset>
<legend>Wolkenhöhen:</legend>
<div id="theCanvas">
<canvas id="cloudCanvas" width="618" height="510" style="border:1px solid #ffffff;">
</canvas>
</div>
<script>
const blu = '#1c29cc';
const wht = '#000000';
const grn = '#008513';
const ylo = '#e2ff28';
const amb = '#9d4600';
const red = '#9d0313';
const gray = '#8f8481';
const black = '#000000';
var maxY = 510;
var minY = 15;
var minX = 10;
var maxX = 600;
function plotGrit() {
var c = document.getElementById("cloudCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(minX+20, minY);
ctx.lineTo(minX+20, maxY-15);
ctx.lineTo(maxX-15, maxY-15);
ctx.strokeStyle = '#c9c9c9';
ctx.stroke();
ctx.closePath();
ctx.font = "10px Arial";
};
function heightLine(hcld,ctxt) {
var arr = {"#9d4600":200,"#e2ff28":300,"#008513":700,"#000000":1500,"#1c29cc":2500};
for (i=0; i<hcld; i+=2000) {
ctxt.beginPath();
ctxt.moveTo(minX+20, (480-480*i/hcld)+minY);
ctxt.lineTo(maxX-15, (480-480*i/hcld)+minY);
ctxt.strokeStyle = gray;
ctxt.stroke();
ctxt.closePath();
ctxt.fillStyle = black;
ctxt.fillText(i, minX-10, (480-480*i/hcld)+minY);
}
for(var key in arr)
{
var hgt = arr[key];
ctxt.beginPath();
ctxt.moveTo(minX+20, (480-480*hgt/hcld)+minY);
ctxt.lineTo(maxX-15, (480-480*hgt/hcld)+minY);
ctxt.strokeStyle = key;
ctxt.stroke();
ctxt.closePath();
}
}
function timeLine(x,ctxt, col) {
ctxt.beginPath();
ctxt.moveTo(x, minY);
ctxt.lineTo(x, maxY-15);
ctxt.lineWidth = 1;
ctxt.strokeStyle = col;
ctxt.stroke();
ctxt.closePath();
}
function cldDot(hgt, x, y ,ctxt) {
// plots a dot representing the measured cloud height
if (hgt >= 2500) {
col = blu;
} else if (hgt >= 1500) {
col = wht;
} else if (hgt >= 700) {
col = grn;
} else if (hgt >= 300) {
col = ylo;
} else if (hgt >= 200) {
col = amb;
} else if ((hgt > 0) && (hgt < 200)) {
col = red;
}
ctxt.fillStyle = col;
ctxt.fillRect(x-3,y-3,3,3);
}
function fetchClouds() {
var multiplier = 1/1000;
var lcld = 400000;
var hcld = 0;
var X = minX+20;
var c = document.getElementById("cloudCanvas");
var ctx = c.getContext("2d");
$.ajax({
type: "Post",
url: "cloudQuery.php?tsteps=180",
success: function(data) {
var obj = $.parseJSON(data);
// Printing all the values from the resulting object
for (var i in obj ) {
cld = obj[i]['cldLyr_Service1'];
cld2 = obj[i]['cldLyr_Service2'];
cld3 = obj[i]['cldLyr_Service3'];
if (cld < lcld && cld != 0) {
lcld = cld;
}
if (cld > hcld) {
hcld = cld;
}
var min = obj[i]['Time'].substring(3,5);
if (min == 00) {
timeLine(X,ctx,black);
ctx.fillStyle = "black";
ctx.fillText(obj[i]['Time'], X-13, maxY-5);
}
if ((min % 10 == 0) && (min != 00)) {
timeLine(X,ctx,gray);
ctx.fillStyle = "black";
ctx.fillText(min, X-7, maxY-5);
}
cldDot(cld, X,(480-480*cld/hcld)+minY,ctx);
if (cld2 > 0) {
cldDot(cld2, X,(480-480*cld2/hcld)+minY,ctx);
}
if (cld3 > 0) {
cldDot(cld3, X,(480-480*cld3/hcld)+minY,ctx);
}
X+=3;
}
heightLine(hcld,ctx);
lcld = 0 + " ft";
ctx.fillStyle = "black";
ctx.fillText(lcld, minX-10, maxY-15);
hcld = hcld + " ft";
ctx.fillText(hcld, minX-10, maxY-490);
}
});
};
fetchClouds();
plotGrit();
$(document).ready(function() {
setInterval(fetchClouds, 1000);
});
</script>
</fieldset>
The result looks like
I have a repeat function which runs on a button on-click event, however it's not working properly. Maybe because there are too many setIntervals running although I tried to clear them all. I also made sure to reset the variables used back to their initial values, however the moving circle keeps showing up faded when the shoot again button is pressed, so I'm assuming there's an issue with the setInterval, however, I don't know what it is.It's also not drawing the basketball again.
var level = prompt("Type 1 for hard, 2 for medium, and 3 for easy.")
var dt = level / 100;
var ctx = canvas.getContext("2d");
var intervalId2;
var intervalId1;
//Initializing Variables
var dt = level / 100;
const PI = 3.14;
var r = 20;
var x = r + 1;
var y = 500 / 1.2;
var a = 1;
var shift = 380;
var leftshift = 35;
var xc = 145;
var yc = 300;
var rc = 50;
var dxc = 95;
var dyc = 300;
var theta = 0;
var resetVars = function() {
dt = 0.01;
var x = r + 1;
var y = 500 / 1.2;
var xc = 145;
var yc = 300;
var dxc = 95;
var dyc = 300;
var theta = 0;
};
//resetVars();
var reset = function() {
ctx.clearRect(0, 0, 800, 800);
drawHoop()
};
//Interval Id to eventually clear it to stop this to shoot
var intervalID = setInterval(moveCirc, 10000 * dt);
var count = 0;
//shoot when spacebar is pressed
document.body.onkeyup = function(shoot1) {
if (dxc <= 110 && shoot1.keyCode == 32) {
console.log(dxc);
clearInterval(intervalID);
make();
count = count + 1;
document.getElementById("count").innerHTML = "You've made " + count + " baskets.";
}
if (dxc > 110 && shoot1.keyCode == 32) {
console.log(dxc);
clearInterval(intervalID);
miss();
document.getElementById("count").innerHTML = "You've made " + count + " baskets.";
}
};
var repeat = function() {
reset();
clearInterval(intervalID);
clearInterval(intervalId2);
clearInterval(intervalId1);
resetVars();
drawBasketball();
drawHoop();
moveCirc();
intervalID = setInterval(moveCirc, 10000 * dt);
document.body.onkeyup = function(shoot1) {
if (dxc <= 110 && shoot1.keyCode == 32) {
console.log(dxc);
clearInterval(intervalID);
make();
count = count + 1;
document.getElementById("count").innerHTML = "You've made " + count + " baskets.";
}
if (dxc > 110 && shoot1.keyCode == 32) {
console.log(dxc);
clearInterval(intervalID);
miss();
document.getElementById("count").innerHTML = "You've made " + count + " baskets.";
}
};
};
<html>
<canvas id="canvas" width="1000" height="500"> </canvas>
<body style="background-color:powderblue;">
<p id="count"></p>
<button id="again" onclick="repeat()"> Shoot Again </button>
</body>
This should make a stop button for a repeating function
<script>
var int=self.setInterval(function, 60000);
</script>
<!-- Stop Button -->
Stop
I'm currently working on a small tile matching game and have made it so that each time you complete the game the variable "bestTime" will store the amount of time you took to complete the session. The variable "bestTimeTxt" will then take the value and display it in text. After you have completed a session a link will appear allowing you to start again. I have put the new text
bestTimeTxt = new Text("Best Time: " + bestTime , "30px Monospace", "#000");
bestTimeTxt.textBaseLine = "top";
bestTimeTxt.x = 500;
bestTimeTxt.y = 100;
outside of the init() function so it shouldn't keep resetting I'm not sure what I am supposed to do as every combination i could think of isn't working.
here is my full code.
I'm also using easeljs for this game
<!DOCTYPE html>
<html>
<head>
<title>Recipe: Drawing a square</title>
<script src="easel.js"></script>
<script type="text/javascript">
var canvas;
var stage;
var squareSide = 70;
var squareOutline = 5;
var max_rgb_color_value = 255;
var gray = Graphics.getRGB(20, 20, 20);
var placementArray = [];
var tileClicked;
var timeAllowable;
var totalMatchesPossible;
var matchesFound;
var txt;
var bestTime = 0;
var bestTimeTxt;
var matchesFoundText;
var squares;
var startingTime;
bestTimeTxt = new Text("Best Time: " + bestTime , "30px Monospace", "#000");
bestTimeTxt.textBaseLine = "top";
bestTimeTxt.x = 500;
bestTimeTxt.y = 100;
function init() {
var rows = 5;
var columns = 6;
var squarePadding = 10;
canvas = document.getElementById('myCanvas');
stage = new Stage(canvas);
var numberOfTiles = rows*columns;
matchesFound = 0;
timeAllowable = 500;
startingTime = timeAllowable;
txt = new Text(timeAllowable, "30px Monospace", "#000");
txt.textBaseline = "top"; // draw text relative to the top of the em box.
txt.x = 500;
txt.y = 0;
stage.addChild(bestTimeTxt);
stage.addChild(txt);
squares = [];
totalMatchesPossible = numberOfTiles/2;
Ticker.init();
Ticker.addListener(window);
Ticker.setPaused(false);
matchesFoundText = new Text("Pairs Found: "+matchesFound+"/"+totalMatchesPossible, "30px Monospace", "#000");
matchesFoundText.textBaseline = "top"; // draw text relative to the top of the em box.
matchesFoundText.x = 500;
matchesFoundText.y = 40;
stage.addChild(matchesFoundText);
setPlacementArray(numberOfTiles);
for(var i=0;i<numberOfTiles;i++){
var placement = getRandomPlacement(placementArray);
if (i % 2 === 0){
var color = randomColor();
}
var square = drawSquare(gray);
square.color = color;
square.x = (squareSide+squarePadding) * (placement % columns);
square.y = (squareSide+squarePadding) * Math.floor(placement / columns);
squares.push(square);
stage.addChild(square);
square.cache(0, 0, squareSide + squarePadding, squareSide + squarePadding);
square.onPress = handleOnPress;
stage.update();
};
}
function drawSquare(color) {
var shape = new Shape();
var graphics = shape.graphics;
graphics.setStrokeStyle(squareOutline);
graphics.beginStroke(gray);
graphics.beginFill(color);
graphics.rect(squareOutline, squareOutline, squareSide, squareSide);
return shape;
}
function randomColor(){
var color = Math.floor(Math.random()*255);
var color2 = Math.floor(Math.random()*255);
var color3 = Math.floor(Math.random()*255);
return Graphics.getRGB(color, color2, color3)
}
function setPlacementArray(numberOfTiles){
for(var i = 0;i< numberOfTiles;i++){
placementArray.push(i);
}
}
function getRandomPlacement(placementArray){
randomNumber = Math.floor(Math.random()*placementArray.length);
return placementArray.splice(randomNumber, 1)[0];
}
function handleOnPress(event){
var tile = event.target;
tile.graphics.beginFill(tile.color).rect(squareOutline, squareOutline, squareSide, squareSide);
if(!!tileClicked === false || tileClicked === tile){
tileClicked = tile;
tileClicked.updateCache("source-overlay");
}else{
if(tileClicked.color === tile.color && tileClicked !== tile){
tileClicked.visible = false;
tile.visible = false;
matchesFound++;
matchesFoundText.text = "Pairs Found: "+matchesFound+"/"+totalMatchesPossible;
if (matchesFound===totalMatchesPossible){
gameOver(true);
}
}else{
tileClicked.graphics.beginFill(gray).rect(squareOutline, squareOutline, squareSide, squareSide);
}
tileClicked.updateCache("source-overlay");
tile.updateCache("source-overlay");
tileClicked = tile;
}
stage.update();
}
function tick() {
secondsLeft = Math.floor((timeAllowable-Ticker.getTime()/1000));
txt.text = secondsLeft;
;
if (secondsLeft <= 0){
gameOver(false);
}
stage.update();
}
function gameOver(win){
Ticker.setPaused(true);
for(var i=0;i<squares.length;i++){
squares[i].graphics.beginFill(squares[i].color).rect(5, 5, 70, 70);
squares[i].onPress = null;
if (win === false){
squares[i].uncache();
}
}
var replayParagraph = document.getElementById("replay");
replayParagraph.innerHTML = "<a href='#' onClick='history.go(0);'>Play Again?</a>";
if (win === true){
matchesFoundText.text = "You win!"
if((startingTime - secondsLeft) > bestTime)
{
bestTime = startingTime - secondsLeft;
bestTimeTxt.text = "Best Time: " + bestTime;
}
}
else
{
txt.text = secondsLeft + "... Game Over";
}
}
function replay(){
init();
}
</script>
</head>
<body onload="init()">
<header id="header">
<p id="replay"></p>
</header>
<canvas id="myCanvas" width="960" height="400"></canvas>
</body>
</html>
In your code, inside gameover method, I see you are using history.go(0) on play again link.
Technically, history.go(0) means to refresh the page and all your variables no matter the scope are set to the initial values.
If you want to retain the best score for the session and continue, use the replay method instead of history.
Updated Code :
replayParagraph.innerHTML = "<a href='#' onClick='replay();'>Play Again?</a>";
Spent 6 hours today building this from a tutorial modifying it for my elements, I've been trying for hours to get it to work and i Just can't :/
Here is a link to the tutorial i was following :
http://gamedevelopment.tutsplus.com/tutorials/create-a-simple-space-shooter-game-in-html5-with-easeljs--active-10944
Zip of all the files including the gifs etc. :
http://www.filedropper.com/shooter_1
Raw Javascript Code:
/* Variable Declarations */
var Lives = new Container(); //stores the lives gfx
var Bullets = new Container(); //stores the bullets gfx
var Enemies = new Container(); //stores the enemies gfx
var Boss_Health = 20;
var Score;
var Gfx_Loaded = 0; //used as a preloader, counts the already loaded items
var Center_X = 960;
var Center_Y = 540;
var Ticker_Listener = new Object(); //used as a Ticker listener
var Timer_Source; //references a setInterval method
/* Define Canvas*/
var canvas;
var stage;
/* Background */
var BG_Img = new Image();
var BG;
var BG2_Img = new Image();
var BG2;
/* Characters */
var Player1_Img = new Image();
var Player1;
/* Enemies */
var Enemy1_Img = new Image();
/* Boss */
var Boss1_Img = new Image();
var Boss1;
/* Lives */
var Life_Img = new Image();
/* Bullets */
var Bullet_Img1 = new Image();
/* Alerts */
var Win_Img = new Image ();
var Lose_Img = new Image ();
var Win;
var Lose;
/*Initiation Function*/
function Main () {
canvas = document.getElementbyId('Shooter');
stage = new stage(canvas);
stage.mouseEventsEnabled = true;
/*Sounds*/
SoundJS.addBatch([
{name:'Boss', src:'Boss.mp3', instances:1},
{name:'Shuriken_Hit', src:'Shuriken_Hit.mp3', instances:10},
{name:'Kunai_Throw', src:'Kunai_Throw.mp3', instances:10}]);
/* Load GFX */
BG_Img.src = 'BG_Img.jpg';
BG_Img.name = 'BG';
BG_Img.onload = loadGfx;
BG2_Img.src = 'BG2_Img.jpg';
BG2_Img.name = 'BG2';
BG2_Img.onload = loadGfx;
Player1_Img.src = 'Naruto_Idle.gif';
Player1_Img.name = 'Player1';
Player1_Img.onload = loadGfx;
Enemy1_Img.src = 'Basic_Enemy.gif';
Enemy1_Img.name = 'Enemy1';
Enemy1_Img.onload = loadGfx;
Boss1_Img.src = 'Akatsuki_Boss.gif';
Boss1_Img.name = 'Boss1';
Boss1_Img.onload = loadGfx;
Life_Img.src = 'Life.gif';
Life_Img.name = 'Life';
Life_Img.onload = loadGfx;
Bullet_Img1.src = 'Rasengan_Mid_Air.gif';
Bullet_Img1.name = 'Bullet';
Bullet_Img1.onload = loadGfx;
Win_Img.src = 'Game_Win.gif';
Win_Img.name = 'Game_Win';
Win_Img.onload = loadGfx;
Lose_Img.src = 'Game_Over.gif';
Lose_Img.name = 'Game_Over';
Lose_Img.onload = loadGfx;
/* Ticker */
Ticker.setFPS(30);
Ticker.addListener(stage);
}
/*Preload Function */
function loadGfx(e)
{
if(e.target.name = 'BG'){BG = new Bitmap(BG_Img);}
if(e.target.name = 'BG2'){BG2 = new Bitmap(BG2_Img);}
if(e.target.name = 'Player1'){Player1 = new Bitmap(Player1_Img);}
gfxLoaded++;
if(gfxLoaded == 9)
{
addGameView();
}
}
/* Game View Function */
function addGameView()
{
Player1.x = Center_X - 18.5;
Player1.y = 480 + 34;
/* Add Lives */
for(var i = 0; i < 3; i++)
{
var l = new Bitmap(Life_Img);
l.x = 248 + (25 * i);
l.y = 463;
Lives.addChild(l);
stage.update();
}
/* Score Text */
Score = new Text('0', 'bold 14px Courier New', '#FFFFFF');
Score.maxWidth = 1000; //fix for Chrome 17
Score.x = 2;
Score.y = 476;
/* Second Background */
BG2.y = -480;
/* Add gfx to stage and Tween Ship */
stage.addChild(BG, BG2, Player1, Enemies, Bullets, Lives, Score);
Tween.get(Player1).to({y:425}, 1000).call(Start_Game);
}
/*Move the Player*/
function Move_Player1(e)
{
Player1.x = e.stageX - 18.5;
}
/* Shooting */
function Shoot()
{
var b = new Bitmap(Bullet_Img1);
b.x = Player1.x + 13;
b.y = Player1.y - 20;
Bullets.addChild(b);
stage.update();
SoundJS.play('Kunai_Throw');
}
/* Adding Enemies */
function Add_Enemy ()
{
var e = new Bitmap(Enemy1_Img);
e.x = Math.floor(Math.random() * (320-50))
e.y = -50
Enemies.addChild(e);
stage.update();
}
function Start_Game()
{
stage.onMouseMove = Move_Player1;
BG.onPress = Shoot;
BG2.onPress = Shoot;
Ticker.addListener(Ticker_Listener, false);
Ticker_Listener.tick = update;
Timer_Source = setInterval('addEnemy()', 1000);
}
function update()
{
/* Move Background */
BG.y += 5;
BG2.y += 5;
if(BG.y >= 480)
{
BG.y = -480;
}
else if(BG2.y >= 480)
{
BG2.y = -480;
}
/* Move Bullets */
for(var i = 0; i < Bullets.children.length; i++)
{
Bullets.children[i].y -= 10;
}
/* Clear offstage Bullets */
if(Bullets.children[i].y < - 20)
{
Bullets.removeChildAt(i);
}
}
/* Show Boss */
if(parseInt(Score.text) >= 1000 && Boss1 == null)
{
Boss1 = new Bitmap(Boss1_Img);
SoundJS.play('Boss');
Boss1.x = Center_X - 90;
Boss1.y = -183;
stage.addChild(boss1);
Tween.get(boss1).to({y:40}, 2000) //tween the boss onto the play area
}
/* Move Enemies */
for(var j = 0; j < Enemies.children.length; j++)
{
eEemies.children[j].y += 5;
/* Remove Offstage Enemies */
if(Enemies.children[j].y > 480 + 50)
{
Enemies.removeChildAt(j);
}
}
/* Bullet - Enemy Collision */
for(var k = 0; k < Bullets.children.length; k++)
{
if(Bullets.children[k].x >= Enemies.children[j].x && Bullets.children[k].x + 11 < Enemies.children[j].x + 49 && Bullets.children[k].y < Enemies.children[j].y + 40)
{
Bullets.removeChildAt(k);
Enemies.removeChildAt(j);
stage.update();
SoundJS.play('Shuriken_Hit');
Score.text = parseFloat(Score.text + 50);
}
/* Bullet - Boss Collision */
if(Boss1 != null && bullets.children[k].x >= Boss1.x && Bullets.children[k].x + 11 < Boss1.x + 183 && Bullets.children[k].y < Boss1.y + 162)
{
Bullets.removeChildAt(k);
Boss_Health--;
stage.update();
SoundJS.play('Shuriken_Hit');
Score.text = parseInt(Score.text + 50);
}
}
/* Player1 - Enemy Collision */
if(Enemies.hitTest(Player1.x, Player1.y) || Enemies.hitTest(Player1.x + 37, Player1.y))
{
Enemies.removeChildAt(j);
Lives.removeChildAt(Lives.length);
Player1.y = 480 + 34;
Tween.get(Player1).to({y:425}, 500)
SoundJS.play('Shuriken_Hit');
}
/* Check for win */
if(Boss1 != null && Boss_Health <= 0)
{
alert('Win');
}
/* Check for lose */
if(Lives.children.length <= 0)
{
alert('Lose');
}
function alert(e)
{
/* Remove Listeners */
stage.onMouseMove = null;
BG.onPress = null;
BG2.onPress = null;
Ticker.removeListener(Ticker_Listener);
Ticker_Listener = null;
Timer_Source = null;
/* Display Correct Message */
if(e == 'Win')
{
Win = new Bitmap(Win_Img);
Win.x = centerX - 64;
Win.y = centerY - 23;
stage.addChild(Win);
stage.removeChild(Enemies, Boss1);
}
else
{
Lose = new Bitmap(Lose_Img);
Lose.x = centerX - 64;
Lose.y = centerY - 23;
stage.addChild(Lose);
stage.removeChild(Enemies, Player1);
}
BG.onPress = function(){window.location.reload();};
BG2.onPress = function(){window.location.reload();};
stage.update();
}
Raw HTML Code:
<!doctype html>
<html>
<head>
<title>Scrolling Shooter</title>
<meta charset="utf-8">
<style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style>
<link rel="stylesheet" href="Week11.css">
<script src="https://code.createjs.com/easeljs-0.8.1.min.js"></script>
<script src="https://code.createjs.com/tweenjs-0.6.1.min.js"></script>
<script src="https://code.createjs.com/soundjs-0.6.1.min.js"></script>
</head>
<body onload="Main();">
<div id="stage">
<canvas id= "Shooter"> width="1920" height="1080" </canvas>
</div>
<script src="Main.js"> </script>
</body>
</html>
The tutorial you are using is sorely out-of-date (it uses a version of CreateJS that is 3 or 4 years old). The version of EaselJS you are using in your sample was published in May 2015.
To start with, all CreateJS classes (such as Container) need to use the createjs namespace:
Player1 = new createjs.Bitmap(Player1_Img);
Score = new createjs.Text('0', 'bold 14px Courier New', '#FFFFFF');
The Ticker API has also changed:
createjs.Ticker.addEventListener("tick", stage);
// OR
createjs.Ticker.on("tick", stage);
There are also other APIs that have changed (BitmapAnimation became Sprite for example).
I would start there, and then follow up here once you have made some progress. Use your console to determine what errors are happening, and solve them one at a time.
Cheers,
I am trying to get the distance between my character and the ground, I have found something that looks like it should do what I want but it has been written for another version of box2d.
Original:
float targetHeight = 3;
float springConstant = 100;
//make the ray at least as long as the target distance
b2Vec2 startOfRay = m_hovercarBody->GetPosition();
b2Vec2 endOfRay = m_hovercarBody->GetWorldPoint( b2Vec2(0,-5) );
overcarRayCastClosestCallback callback;
m_world->RayCast(&callback, startOfRay, endOfRay);
if ( callback.m_hit ) {
float distanceAboveGround = (startOfRay - callback.m_point).Length();
//dont do anything if too far above ground
if ( distanceAboveGround < targetHeight ) {
float distanceAwayFromTargetHeight = targetHeight - distanceAboveGround;
m_hovercarBody->ApplyForce( b2Vec2(0,springConstant*distanceAwayFromTargetHeight),
m_hovercarBody->GetWorldCenter() );
}
}
I have tried to change it to what I think it should be but it doesn't even call the callback.
var targetHeight = 3;
var springConstant = 100;
//make the ray at least as long as the target distance
startOfRay = new b2Vec2(m_hovercarBody.GetPosition());
endOfRay = new b2Vec(m_hovercarBody.GetWorldPoint( b2Vec2(0,-5)));
function callback(raycast){
if ( raycast.m_hit ) {
var distanceAboveGround = (startOfRay - raycast.m_point).Length();
//dont do anything if too far above ground
if ( distanceAboveGround < targetHeight ) {
var distanceAwayFromTargetHeight = targetHeight - distanceAboveGround;
m_hovercarBody.ApplyForce( b2Vec2(0,springConstant*distanceAwayFromTargetHeight),
m_hovercarBody.GetWorldCenter() );
}
}
}
m_world.RayCast(callback, startOfRay, endOfRay);
Any idea how to convert it to work with box2dweb?
Thanks
It might be that the original bit of code was written for a platform where the coordinate system works differently.
In a Canvas element, the coordinate system starts from the top left corner, meaning that m_hovercarBody.GetWorldPoint( b2Vec2(0,-5)) is checking for a point above the character, rather than below.
I'm not sure about the rest of the code but try changing that to m_hovercarBody.GetWorldPoint( b2Vec2(0,5)) and see what happens.
EDIT:
I think actually the problem is with the way you've structured your callback. Looking up the reference for the Raycast function would reveal more.
(The Javascript version of Box2D you're using is an automatic port of the Actionscript one. Given the two have fairly similar syntax, you can use the reference for Flash.)
The original code you posted seems to be C++, but I don't know much about its syntax. It seems there's some sort of class that does the raycasting (overcarRayCastClosestCallback). You can either look for that, or try and build your own callback function according to the first link I posted. It would be something along the lines of:
function customRaycastCallback(fixture, normal, fraction) {
// you can, for instance, check if fixture belongs to the ground
// or something else, then handle things accordingly
if( /* fixture belongs to ground */ ) {
// you've got the fraction of the original length of the raycast!
// you can use this to determine the distance
// between the character and the ground
return fraction;
}
else {
// continue looking
return 1;
}
}
Try running this on your browser. I coded this when I was learning sensor and RAYCAST in Box2Dweb. Hope it helps.
<html>
<head>
<title>Box2dWeb Demo</title>
</head>
<body>
<canvas id="canvas" width="600" height="420" style="background-color:#333333;" ></canvas>
<div id="cc" style="position:absolute; right:0; top:100px; width:500px; height:50px; margin:0;"></div>
</body>
<script type="text/javascript" src="Box2dWeb-2.1.a.3.js"></script>
<script type="text/javascript" src="jquery-1.7.2.js"></script>
<script type="text/javascript">
var b2Vec2 = Box2D.Common.Math.b2Vec2
, b2BodyDef = Box2D.Dynamics.b2BodyDef
, b2Body = Box2D.Dynamics.b2Body
, b2FixtureDef = Box2D.Dynamics.b2FixtureDef
, b2World = Box2D.Dynamics.b2World
, b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
, b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
, b2ContactFilter = Box2D.Dynamics.b2ContactFilter
, b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef
, b2DebugDraw = Box2D.Dynamics.b2DebugDraw
, b2Fixture = Box2D.Dynamics.b2Fixture
, b2AABB = Box2D.Collision.b2AABB
, b2WorldManifold = Box2D.Collision.b2WorldManifold
, b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint
, b2RayCastInput = Box2D.Collision.b2RayCastInput
, b2RayCastOutput = Box2D.Collision.b2RayCastOutput
, b2Color = Box2D.Common.b2Color;
var world = new b2World(new b2Vec2(0,10), true);
var canvas = $('#canvas');
var context = canvas.get(0).getContext('2d');
//box
var bodyDef = new b2BodyDef;
bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.Set(9,7);
bodyDef.userData = 'box';
var fixDef = new b2FixtureDef;
fixDef.filter.categoryBits = 1;
fixDef.density = 10.0;
fixDef.friction = 0.5;
fixDef.restitution = .5;
fixDef.shape = new b2PolygonShape;
fixDef.shape.SetAsBox(1,5);
var box1 = world.CreateBody(bodyDef);
box1.CreateFixture(fixDef);
//circle
var bodyDef2 = new b2BodyDef;
bodyDef2.type = b2Body.b2_dynamicBody;
bodyDef2.position.Set(4,8);
bodyDef2.userData = 'obj';
var fixDef2 = new b2FixtureDef;
fixDef2.filter.categoryBits = 2;
fixDef2.filter.maskBits = 13;
fixDef2.density = 10.0;
fixDef2.friction = 0.5;
fixDef2.restitution = .2;
fixDef2.shape = new b2CircleShape(1);
//circlesensor
var cc = new b2FixtureDef;
cc.shape = new b2CircleShape(2);
cc.shape.SetLocalPosition(new b2Vec2(0 ,0));
cc.density = 0;
cc.isSensor = true;
cc.filter.categoryBits = 8;
var wheel = world.CreateBody(bodyDef2);
wheel.CreateFixture(fixDef2);
wheel.CreateFixture(cc);
//create a ground
var holderDef = new b2BodyDef;
holderDef.type = b2Body.b2_staticBody;
holderDef.userData = "ground";
holderDef.position.Set(10, 14);
var fd = new b2FixtureDef;
fd.filter.categoryBits = 4;
fd.shape = new b2PolygonShape;
fd.shape.SetAsBox(10,1);
var ground = world.CreateBody(holderDef);
ground.CreateFixture(fd);
//create another static body
var holderDef = new b2BodyDef;
holderDef.type = b2Body.b2_staticBody;
holderDef.position.Set(10, 20);
var temp = world.CreateBody(holderDef);
temp.CreateFixture(fd);
var c=0;
$(window).keydown(function(e) {
$('#aa').html(++c);
code = e.keyCode;
if(c==1) {
if(code == 38 && onground)
wheel.SetLinearVelocity(new b2Vec2(0,-10));
if(code == 39)
wheel.ApplyForce(new b2Vec2(1000,0), box1.GetWorldPoint(new b2Vec2(0,0)));
if(code == 37)
wheel.ApplyForce(new b2Vec2(-1000,0), box1.GetWorldPoint(new b2Vec2(0,0)));
}
});
$(window).keyup(function(e) {
c=0;
});
var listener = new Box2D.Dynamics.b2ContactListener;
listener.BeginContact = function(contact) {
if(contact.GetFixtureA().GetBody().GetUserData()== 'obj' || contact.GetFixtureB().GetBody().GetUserData()== 'obj' ) // think about why we don't use fixture's userData directly.
onground = true;// don't put 'var' here!
fxA=contact.GetFixtureA();
fxB=contact.GetFixtureB();
sA=fxA.IsSensor();
sB=fxB.IsSensor();
if((sA && !sB) || (sB && !sA)) {
if(sA) {
$('#cc').prepend(contact.GetFixtureB().GetBody().GetUserData() + ' is in the viscinity of body '+contact.GetFixtureA().GetBody().GetUserData()+'<br>');
}
else {
$('#cc').prepend(contact.GetFixtureA().GetBody().GetUserData() + ' is in the viscinity of body '+contact.GetFixtureB().GetBody().GetUserData()+'<br>');
}
}
}
listener.EndContact = function(contact) {
if (contact.GetFixtureA().GetBody().GetUserData()== 'obj' || contact.GetFixtureB().GetBody().GetUserData()== 'obj' )
onground = false;
}
var debugDraw = new b2DebugDraw();
debugDraw.SetSprite ( document.getElementById ("canvas").getContext ("2d"));
debugDraw.SetDrawScale(30); //define scale
debugDraw.SetAlpha(1);
debugDraw.SetFillAlpha(.3); //define transparency
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
world.SetDebugDraw(debugDraw);
window.setInterval(update,1000/60);
//mouse
var mouseX, mouseY, mousePVec, isMouseDown, selectedBody, mouseJoint;
var canvasPosition = getElementPosition(document.getElementById("canvas"));
document.addEventListener("mousedown", function(e) {
isMouseDown = true;
handleMouseMove(e);
document.addEventListener("mousemove", handleMouseMove, true);
}, true);
document.addEventListener("mouseup", function() {
document.removeEventListener("mousemove", handleMouseMove, true);
isMouseDown = false;
mouseX = undefined;
mouseY = undefined;
}, true);
function handleMouseMove(e) {
mouseX = (e.clientX - canvasPosition.x) / 30;
mouseY = (e.clientY - canvasPosition.y) / 30;
};
function getBodyAtMouse() {
mousePVec = new b2Vec2(mouseX, mouseY);
var aabb = new b2AABB();
aabb.lowerBound.Set(mouseX - 0.001, mouseY - 0.001);
aabb.upperBound.Set(mouseX + 0.001, mouseY + 0.001);
// Query the world for overlapping shapes.
selectedBody = null;
world.QueryAABB(getBodyCB, aabb);
return selectedBody;
}
function getBodyCB(fixture) {
if(fixture.GetBody().GetType() != b2Body.b2_staticBody) {
if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) {
selectedBody = fixture.GetBody();
return false;
}
}
return true;
}
//at global scope
var currentRayAngle = 0;
var input = new b2RayCastInput();
var output = new b2RayCastOutput();
var b = new b2BodyDef();
var f = new b2FixtureDef();
var closestFraction = 1;
var intersectionNormal = new b2Vec2(0,0);
var intersectionPoint = new b2Vec2();
rayLength = 25; //long enough to hit the walls
var p1 = new b2Vec2( 11, 7 ); //center of scene
var p2 = new b2Vec2();
var normalEnd = new b2Vec2();
function update() {
if(isMouseDown && (!mouseJoint)) {
var body = getBodyAtMouse();
if(body) {
var md = new b2MouseJointDef();
md.bodyA = world.GetGroundBody();
md.bodyB = body;
md.target.Set(mouseX, mouseY);
md.collideConnected = true;
md.maxForce = 300.0 * body.GetMass();
mouseJoint = world.CreateJoint(md);
body.SetAwake(true);
}
}
if(mouseJoint) {
if(isMouseDown) {
mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY));
} else {
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
world.Step(1 / 60, 10, 10);
world.DrawDebugData();
world.ClearForces();
world.SetContactListener(listener);
ray();
};
function ray() {
//in Step() function
var k = 360/20;
var t = k/60;
var DEGTORAD = Math.PI/180;
currentRayAngle += t * DEGTORAD; //one revolution every 20 seconds
//console.log(currentRayAngle*(180/Math.PI));
//calculate points of ray
p2.x = p1.x + rayLength * Math.sin(currentRayAngle);
p2.y = p1.y + rayLength * Math.cos(currentRayAngle);
input.p1 = p1;
input.p2 = p2;
input.maxFraction = 1;
closestFraction = 1;
var b = new b2BodyDef();
var f = new b2FixtureDef();
for(b = world.GetBodyList(); b; b = b.GetNext()) {
for(f = b.GetFixtureList(); f; f = f.GetNext()) {
if(!f.RayCast(output, input))
continue;
else if(output.fraction < closestFraction) {
closestFraction = output.fraction;
intersectionNormal = output.normal;
}
}
}
intersectionPoint.x = p1.x + closestFraction * (p2.x - p1.x);
intersectionPoint.y = p1.y + closestFraction * (p2.y - p1.y);
normalEnd.x = intersectionPoint.x + intersectionNormal.x;
normalEnd.y = intersectionPoint.y + intersectionNormal.y;
context.strokeStyle = "rgb(255, 255, 255)";
context.beginPath(); // Start the path
context.moveTo(p1.x*30,p1.y*30); // Set the path origin
context.lineTo(intersectionPoint.x*30, intersectionPoint.y*30); // Set the path destination
context.closePath(); // Close the path
context.stroke();
context.beginPath(); // Start the path
context.moveTo(intersectionPoint.x*30, intersectionPoint.y*30); // Set the path origin
context.lineTo(normalEnd.x*30, normalEnd.y*30); // Set the path destination
context.closePath(); // Close the path
context.stroke(); // Outline the path
}
//helpers
//http://js-tut.aardon.de/js-tut/tutorial/position.html
function getElementPosition(element) {
var elem=element, tagname="", x=0, y=0;
while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
y += elem.offsetTop;
x += elem.offsetLeft;
tagname = elem.tagName.toUpperCase();
if(tagname == "BODY")
elem=0;
if(typeof(elem) == "object") {
if(typeof(elem.offsetParent) == "object")
elem = elem.offsetParent;
}
}
return {x: x, y: y};
}
</script>
</html>
Here's a Raycast in Box2dWeb that I got working:
var p1 = new b2Vec2(body.GetPosition().x, body.GetPosition().y); //center of scene
var p2 = new b2Vec2(body.GetPosition().x, body.GetPosition().y + 5); //center of scene
world.RayCast(function(x){
console.log("You've got something under you");
}, p1,p2);