So basically i had some code of a car that has speed and everything, now i want another one with the same properties. So i duplicated the whole code and changed the other cars url and all of the variables for it. I get 2 cars on my canvas but they keep blinking. I dont know why that is happening.
You can see it for yourself on JsBin:
http://jsbin.com/fekutakime/3/edit
The car code that i duplicated is:
//Setting the canvas and context
var canvas = document.getElementById('gameCanvas');
var context = canvas.getContext('2d');
//Uploading car
var car = new Image();
car.src = "http://images.clipartpanda.com/car-top-view-clipart-red-racing-car-top-view-fe3a.png";
//Setting properties of car
var x = 450;
var y = 730;
var speed = 10;
var angle = 990;
var mod = 0;
//Event listeners for keys
window.addEventListener("keydown", keypress_handler, false);
window.addEventListener("keyup", keyup_handler, false);
//Interval for animation
var moveInterval = setInterval(function () {
draw();
}, 30);
//Drawing the car turning and changing speed
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
x += (speed * mod) * Math.cos(Math.PI / 180 * angle);
y += (speed * mod) * Math.sin(Math.PI / 180 * angle);
context.save();
context.translate(x, y);
context.rotate(Math.PI / 180 * angle);
context.drawImage(car, -(car.width / 2), -(car.height / 2));
context.restore();
}
//Setting the keys
function keyup_handler(event) {
if (event.keyCode == 38 || event.keyCode == 40) {
mod = 0;
}
}
//Setting all of the keys
function keypress_handler(event) {
console.log(x, y);
if (event.keyCode == 38) {
mod = 1;
}
if (event.keyCode == 40) {
mod = -1;
}
if (event.keyCode == 37) {
angle -= 5;
}
if (event.keyCode == 39) {
angle += 5;
}
}
Related
I'm pretty new to this and I got the animation working by watching a youtube tutorial.
Here is a canvas animation of a keyboard controlled car.
http://jsfiddle.net/unn9P/
canvas = document.getElementById('canvas');
c = canvas.getContext('2d');
c.clear = function() {
this.clearRect(0,0,1500,1500) };
function wait(fn) {
window.setTimeout(fn, 250) }
function repeat(fn) {
if (requestAnimationFrame) {
var advance = function() {fn(); requestAnimationFrame(advance);};
requestAnimationFrame(advance);
} else window.setInterval(fn, 50);
}
var dx = 0, dy = 0, mousex = 0, mousey=0, mouseclicks = 0;
document.onkeydown = function(e) {
var key = e.keyCode;
if (key == 37) dx=-1;
else if (key == 38) dy=-1;
else if (key == 39) dx=1;
else if (key == 40) dy=1;
else return true;
return false;
};
document.onkeyup = function(e) {
var key = e.keyCode;
if (key == 37 || key == 39) dx=0;
else if (key == 38 || key == 40) dy=0;
else return true;
return false;
};
canvas.onmousemove = function(e) {
var rect = canvas.getBoundingClientRect();
mousex = e.clientX - rect.left;
mousey = e.clientY - rect.top;
};
canvas.onmousedown = function(e) {mouseclicks++;};
a = new Image();
a.src = 'http://o.ooli.ca/car_top.png';
wait(function(){
x = 50;
y = 50;
angle = 0;
repeat(function() {
angle = angle + dx;
x = x - dy * Math.cos(angle * Math.PI / 180);
y = y - dy * Math.sin(angle * Math.PI / 180);
c.clear();
c.translate(x, y);
c.rotate(angle * Math.PI / 180);
c.translate(-37, -19);
c.drawImage(a, 0, 0);
c.setTransform(1, 0, 0, 1, 0, 0); //reset
});
});
Now I would like to add trail behind the car as it moves along and create a reset button inside the canvas which can help me clear the trail, and bring the car to its initial position.
I have read some tutorials but i can't seem to find what I want.
Is there any idea/suggestion on how I should do this?
Simply record your points when moving:
Modified fiddle here
repeat(function () {
angle = angle + dx;
x = x - dy * Math.cos(angle * Math.PI / 180);
y = y - dy * Math.sin(angle * Math.PI / 180);
/// record point
pts.push([x, y]);
c.clear();
/// render points (see below)
renderTrail(pts, c);
c.translate(x, y);
...
Then have a function to render the recorded points:
function renderTrail(pts, c) {
if (pts.length > 1) {
c.beginPath();
c.moveTo(pts[0][0], pts[0][1]);
for(var i = 1, pt; pt = pts[i]; i++) {
c.lineTo(pt[0], pt[1]);
}
c.stroke();
}
}
To reset just clear the point array:
pts = [];
You can do this on a mouse-click event on the canvas where you chose to draw your button or just put a html button on top of canvas (above it, literally on top will reduce the performance of canvas).
I am trying to animate many objects to a canvas using KineticJS. I am using the built-in move method on every frame. It is known that redrawing a layer is an expensive operation which can cause performance issues, so I am calling layer.draw() only after each move operations has already been executed. Despite this, the more objects I animate, the poor the performance becomes and the end result is a sluggish animation.
To compare the KineticJS performance against the native canvas, I prepared two demos that do the same thing - bouncing balls in a canvas of 500x500. The first one is using the native canvas. It just clears the canvas on each frame and draws the balls. The second one uses KineticJS and once the image objects are created, it uses the move method to move them.
It is obvious that while the native demo performs the same with 10, 100 and 1000 balls, the performance of KineticJS demo is strongly affected by the number of balls. With 1000, it is just unusable. There are many optimizations that can be made to both examples, including using requestAnimationFrame for animation loop or using the built-in Animation object for KineticJS, but these will not change the performance of the demos much.
So here are the two demos. First, the native one - http://jsfiddle.net/uxsLN/1/
(function() {
window.addEventListener('load', loaded, false);
function loaded() {
img = new Image();
img.onload = canvasApp;
img.src = 'ball.png';
}
function canvasApp() {
var theCanvas = document.getElementById("canvas");
var context = theCanvas.getContext("2d");
function drawScreen() {
context.clearRect(0, 0, theCanvas.width, theCanvas.height);
context.strokeStyle = '#000000';
context.strokeRect(1, 1, theCanvas.width - 2, theCanvas.height - 2);
context.fillStyle = "#000000";
var ball;
for (var i = 0; i < balls.length; i++) {
ball = balls[i];
ball.x += ball.xunits;
ball.y += ball.yunits;
context.drawImage(img, ball.x, ball.y);
if (ball.x + ball.radius * 2 > theCanvas.width || ball.x < 0) {
ball.angle = 180 - ball.angle;
updateBall(ball);
} else if (ball.y + ball.radius * 2 > theCanvas.height || ball.y < 0) {
ball.angle = 360 - ball.angle;
updateBall(ball);
}
}
}
function updateBall(ball) {
ball.radians = ball.angle * Math.PI / 180;
ball.xunits = Math.cos(ball.radians) * ball.speed;
ball.yunits = Math.sin(ball.radians) * ball.speed;
}
var numBalls = 1000;
var maxSize = 8;
var minSize = 5;
var maxSpeed = maxSize + 5;
var balls = [];
var radius = 24;
for (var i = 0; i < numBalls; i++) {
var speed = maxSpeed - radius;
var angle = Math.floor(Math.random() * 360);
var radians = angle * Math.PI / 180;
var ball = {
x : (theCanvas.width - radius) / 2,
y : (theCanvas.height - radius) / 2,
radius : radius,
speed : speed,
angle : angle,
xunits : Math.cos(radians) * speed,
yunits : Math.sin(radians) * speed
}
balls.push(ball);
}
function gameLoop() {
window.setTimeout(gameLoop, 20);
drawScreen()
}
gameLoop();
}
})();
Next, KineticJS - http://jsfiddle.net/MNpUX/
(function() {
window.addEventListener('load', loaded, false);
function loaded() {
img = new Image();
img.onload = canvasApp;
img.src = 'ball.png';
}
function canvasApp() {
var stage = new Kinetic.Stage({
container : 'container',
width : 500,
height : 500
});
var layer = new Kinetic.Layer();
stage.add(layer);
rect = new Kinetic.Rect({
x : 0,
y : 0,
width : stage.getWidth(),
height : stage.getHeight(),
fill : '#EEEEEE',
stroke : 'black'
});
layer.add(rect);
function drawScreen() {
var ball;
for ( var i = 0; i < balls.length; i++) {
ball = balls[i];
ball.obj.move(ball.xunits, ball.yunits);
if (ball.obj.getX() + ball.radius * 2 > stage.getWidth() || ball.obj.getX() < 0) {
ball.angle = 180 - ball.angle;
updateBall(ball);
} else if (ball.obj.getY() + ball.radius * 2 > stage.getHeight() || ball.obj.getY() < 0) {
ball.angle = 360 - ball.angle;
updateBall(ball);
}
}
layer.draw();
}
function updateBall(ball) {
ball.radians = ball.angle * Math.PI / 180;
ball.xunits = Math.cos(ball.radians) * ball.speed;
ball.yunits = Math.sin(ball.radians) * ball.speed;
}
var numBalls = 1000;
var maxSize = 8;
var minSize = 5;
var maxSpeed = maxSize + 5;
var balls = [];
var radius = 24;
for ( var i = 0; i < numBalls; i++) {
var speed = maxSpeed - radius;
var angle = Math.floor(Math.random() * 360);
var radians = angle * Math.PI / 180;
var obj = new Kinetic.Image({
image : img,
x : (stage.getWidth() - radius) / 2,
y : (stage.getHeight() - radius) / 2
});
layer.add(obj);
var ball = {
radius : radius,
speed : speed,
angle : angle,
xunits : Math.cos(radians) * speed,
yunits : Math.sin(radians) * speed,
obj : obj
};
balls.push(ball);
}
function gameLoop() {
window.setTimeout(gameLoop, 20);
drawScreen()
}
gameLoop();
}
})();
So the question is - do I miss something about KineticJS or it is just not built for such a purpose?
You can gain a little speed by:
Turning listening off on the stage.
Using layer.drawScene instead of layer.draw. (drawScene doesn't also redraw the hit scene).
Reducing the ball count to 500 (the effect looks pretty much the same).
If your design permits, use a custom Kinetic.Shape to get "closer to the metal".
The Kinetic.Shape gives you a wrapped Context on which you can run native Context commands.
Using Shape, you'll get magnitudes better results because there's only 1 object being managed.
Here's code and a Fiddle: http://jsfiddle.net/m1erickson/AVJyr/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:500px;
height:500px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500,
listening:false
});
var layer = new Kinetic.Layer();
stage.add(layer);
//
var cw=stage.getWidth();
var ch=stage.getHeight();
var numBalls = 1000;
var maxSize = 8;
var minSize = 5;
var maxSpeed = maxSize + 5;
var balls = [];
var radius = 24;
// this is a custom Kinetic.Shape
var shape;
for (var i = 0; i < numBalls; i++) {
var speed = maxSpeed - radius;
var angle = Math.floor(Math.random() * 360);
var radians = angle * Math.PI / 180;
var ball = {
x : (cw-radius)/2,
y : (ch-radius)/2,
radius : radius,
speed : speed,
angle : angle,
xunits : Math.cos(radians) * speed,
yunits : Math.sin(radians) * speed
}
balls.push(ball);
}
// load the ball image and create the Kinetic.Shape
img = new Image();
img.onload=function(){
shape=new Kinetic.Shape({
x: 0,
y: 0,
width:500,
height:500,
draggable: true,
drawFunc: function(context) {
context.beginPath();
var ball;
for (var i = 0; i < balls.length; i++) {
ball = balls[i];
ball.x += ball.xunits;
ball.y += ball.yunits;
context.drawImage(img, ball.x, ball.y);
if (ball.x+ball.radius*2>cw || ball.x<0) {
ball.angle = 180 - ball.angle;
} else if (ball.y+ball.radius*2>ch || ball.y<0) {
ball.angle = 360 - ball.angle;
}
ball.radians = ball.angle * Math.PI / 180;
ball.xunits = Math.cos(ball.radians) * ball.speed;
ball.yunits = Math.sin(ball.radians) * ball.speed;
}
context.fillStrokeShape(this);
},
});
layer.add(shape);
// GO!
gameLoop();
}
img.src = 'http://users-cs.au.dk/mic/dIntProg/e12/uge/4/Projekter/bouncingballs/assignment/ball.png';
// RAF used to repeatedly redraw the custom shape
function gameLoop(){
window.requestAnimationFrame(gameLoop);
layer.clear();
shape.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>
I've created this animation for my project that had to use any form of physics.
I am a total beginner, too :) Anyway, this is my project now :
Bouncing Balls
You can setup gravity and force, then click play, and just drag and drop to shoot the balls. You can change the values and hit update too see an effect.
My question is, how can I create an effect that when I press ratio button (for example) I can see the path that ball makes? Is it complicated? As I was saying I am a beginner, so no complex code for me :)
Also, doyou have any ideas to make the project better? Any additional "physics" effects? Or maybe you know a website that shows tutorials for simile (please) effects made in HTML5/js so I can add additional effects to my project.
One possibility (as you're clearing the canvas each frame) would be to draw ball paths onto a secondary canvas, which would not be cleared each frame. Then, when you come to clear the first frame, render the second frame after clearing, and before rendering the balls.
The second canvas would of course have to be the same dimensions as the first, so that all of the ball points line up correctly. The second canvas should also have a z-index lower than the first, so that it is only shown when you specifically render it to the first canvas (i.e. when the radio button is checked).
To decrease any lag while the radio is not checked, you could skip drawing the ball paths to the second canvas, although I don't think you would see any great increase in performance.
On each frame update, you would mark the position of each ball with a pixel, or line (from the previous position to the current) on the second canvas.
Looking at your code, you seem pretty competent, so I've skipped writing an example as I think this would be good experience for you :)
Modified 'script.js' source demonstrating solution
window.onload = function(){
$("#canvas").hide();
var howManyPaths = 0;
var showPath=false;
// SLIDERS
var gravitySlider = document.getElementById('gravitySlider');
var gravityVal = document.getElementById('gravityValue');
gravitySlider.onchange = function(){
gravityVal.value = gravitySlider.value;
}
gravityVal.onkeyup = function(){
gravitySlider.value = gravityVal.value;
}
var forceSlider = document.getElementById('forceSlider');
var forceValue = document.getElementById('forceValue');
forceSlider.onchange = function(){
forceValue.value = forceSlider.value;
}
forceValue.onkeyup = function(){
forceSlider.value = forceValue.value;
}
// GLOBAL VARIABLES
var test = false;
var gravityCount = $("#gravity").val();
var forceCount = $("#rectangles").val();
// CSS :
var playCSS = document.getElementById("play");
var restartCSS = document.getElementById("restart");
var clickableCSS = document.getElementById("setup");
var clickableBG = document.getElementById("img");
//restartCSS.style.visibility="hidden";
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");
//var ctx;
var gravity = 9.86;
var forceFactor = 0.5;
var mouseDown = false;
var balls = new Array();
var mousePos = new Array();
// EVENT HANDLER
function onMouseDown(evt){
mouseDown = true;
mousePos['downX'] = evt.pageX;
mousePos['downY'] = evt.pageY;
}
function onMouseUp(evt){
mouseDown = false;
setup.style.visibility="visible";
if(test == true && !( mousePos['downX'] < 200 && mousePos['downY'] < 150) ){
restartCSS.style.visibility="visible";
forceFactor = forceCount;
balls.push(new ball(mousePos["downX"],
mousePos["downY"],
(evt.pageX - mousePos["downX"]) * forceFactor,
(evt.pageY - mousePos["downY"]) * forceFactor,
10 + (Math.random() * 10),
0.8,
randomColor()
));
}
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
}
function onMouseMove(evt){
mousePos['currentX'] = evt.pageX;
mousePos['currentY'] = evt.pageY;
}
function resizeWindow(evt){
//canvas.height = 960;
//canvas.width = 720;
canvas.height = $(window).height()-6;
canvas.width = $(window).width();
canvas2.height = $(window).height()-6;
canvas2.width = $(window).width();
}
$(document).mousedown(onMouseDown);
$(document).mouseup(onMouseUp);
$(document).mousemove(onMouseMove);
$(window).bind("resize", resizeWindow);
// GRAPHICS CODE
function circle(x, y, r, col){
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2, true);
ctx.closePath;
// fill
ctx.fillStyle = col;
ctx.fill();
// stroke
ctx.lineWidth = r * 0.1;
ctx.strokeStyle = "#000000";
ctx.stroke();
}
function circlePath(x, y)
{
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.fillStyle = '#3f4043';
ctx2.fillRect(x, y, 5, 5);
ctx2.strokeStyle = "black";
ctx2.strokeRect(x, y, 5, 5);
}
function randomColor(){
var letter = "0123456789ABCDEF".split("");
var color = "#";
for(var i=0; i<6; i++){
color += letter[Math.round(Math.random()*15)];
}
return color;
}
function arrow(fromX, fromY, toX, toY, color){
// path
ctx.beginPath();
var headLen = 10;
var angle = Math.atan2(toY - fromY, toX - fromX);
ctx.moveTo(fromX, fromY);
ctx.lineTo(toX, toY);
ctx.lineTo(toX - headLen * Math.cos(angle - Math.PI/6), toY - headLen * Math.sin(angle - Math.PI/6));
ctx.moveTo(toX, toY);
ctx.lineTo(toX - headLen * Math.cos(angle + Math.PI/6), toY - headLen * Math.sin(angle + Math.PI/6));
// style
ctx.lineWith = 1;
ctx.strokeStyle = color;
ctx.lineCap = "butt";
ctx.stroke();
}
function drawBall(){
// Gravity
gravity = gravityCount;
this.speedY += gravity * 0.5; // v = a * t
this.x += this.speedX * 0.05; // s = v * t
this.y += this.speedY * 0.05;
// prawa ściana
if(this.x + this.r > canvas.width){
this.x = canvas.width - this.r;
this.speedX *= -1 * this.bounce;
}
// lewa ściana
if(this.x - this.r < 0){
this.x = this.r;
this.speedX *= -1 * this.bounce;
}
// dolna ściana
if(this.y + this.r > canvas.height){
this.y = canvas.height - this.r;
this.speedY *= -1 * this.bounce;
}
// górna ściana
if(this.y - this.r < 0){
this.y = this.r;
this.speedY *= -1 * this.bounce;
}
// zwalnianie na ziemi
if (this.speedX > 0.25){
this.speedX -= 0.25;
if (this.speedY > 0.25)
this.speedY -= 0.25;
}
if (this.speedX < -0.25){
this.speedX += 0.25;
//if (this.speedY < -0.25)
// this.speedY += 0.25;
}
circle(this.x, this.y, this.r, this.col);;
}
// OBJECTS
function ball(positionX, positionY, sX, sY, radius, b, color){
this.x = positionX;
this.y = positionY;
this.speedX = sX;
this.speedY = sY;
this.r = radius;
this.bounce = b;
this.col = color;
this.draw = drawBall;
}
//GAME LOOP
function gameLoop(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
//grab the context from your destination canvas
//if path drawing is enabled, first draw the path canvas to the display canvas
if (showPath) ctx.drawImage(canvas2,0,0);
if(mouseDown == true){
// ctx.clearRect(0, 0, canvas.width, canvas.height); /* !important !!!!!!!!!!!!!!! */
arrow(mousePos['downX'], mousePos['downY'], mousePos['currentX'], mousePos['currentY'], "red");
}
for(var i=0; i<balls.length; i++){
balls[i].draw();
if (i==balls.length-1) {
//draw path
ctx2.fillStyle = '#3f4043';
ctx2.fillRect(balls[i].x, balls[i].y, 5, 5);
ctx2.strokeStyle = "black";
ctx2.strokeRect(balls[i].x, balls[i].y, 5, 5);
}
}
ctx.fillStyle = "#000000";
ctx.font = "15px Arial";
ctx.fillText("Balls: " + balls.length + " " + gravityCount + " " + forceCount + " " + howManyPaths, 10, canvas.height -10);
}
// START THE GAME
function init(){
//$("#setup").hide();
$("#canvas").show();
$("#canvas2").hide();
ctx = $('canvas')[0].getContext("2d");
canvas.height = $(window).height()-6;
canvas.width = $(window).width();
//canvas.width = 960;
//canvas.height = 720;
canvas2.height = $(window).height()-6;
canvas2.width = $(window).width();
return setInterval(gameLoop, 10);
}
$("#play").click(function() {
test = true;
playCSS.style.visibility="hidden";
gravityCount = $("#gravitySlider").val();
forceCount = $("#forceSlider").val();
init();
});
$("#restart").click(function() {
window.location.href="index.html";
});
$("#refresh").click(function() {
gravityCount = $("#gravitySlider").val();
forceCount = $("#forceSlider").val();
});
$("#showPath").click(function() {
showPath=true;
});
$("#hidePath").click(function() {
showPath=false;
});
}
I'm making a HTML5 Canvas Game with a rectangle that moves around the canvas. The objective is to dodge multiple Balls moving across the canvas for as long as possible. But i'm struggling to put a Timer to show your Time/Score when a ball hits the rectangle. (The rectangle is moved by the UP,DOWN,LEFT and RIGHT keys). Anyone with knowledge of this that could help me out would be much appreciated, thanks.
Here’s how to integrate a timer into your game:
Set the startingTime just before you start the game ticker:
/* Do the function, call every 20 milliseconds*/
startTime=new Date();
Draw the elapsed time whenever playGame is called:
/* MAIN GAME */
function playGame()
{
g.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas at start.
player.draw();
for (var i = 0; i < 8; i++)
{
ball[i].move();
ball[i].draw();
}
// draw the score
drawElapsedTime();
}
And finally, draw the final score when the game is over:
drawFinalScore();
alert("GAME OVER");
Also, I noticed you left the game ticker running even after the game ended. Here’s how to turn off the ticker:
// turn on the ticker and get a reference to the object
var theInterval=setInterval(playGame, 20);
// turn off the ticker
clearInterval(theInterval);
And…check out the new requestAnimationFrame ticker. It’s much more efficient and resource friendly than the older setInterval ticker. Here’s a link for requestAnimationFrame: http://paulirish.com/2011/requestanimationframe-for-smart-animating/
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/8qKht/
<!DOCTYPE html>
<html>
<head>
<style>
body
{
background-color:green;
}
#simpleCanvas
{
position: absolute;
top: 20%;
left: 30%;
border:2px solid blue;
width:500px;
height:500px;
background-color: yellow;
}
</style>
<script>
/* Ball Array */
var ball = new Array();
ball[0] = new Ball(150, 150); // x location of target, y location of target
ball[1] = new Ball(200, 350);
ball[2] = new Ball(400, 350);
ball[3] = new Ball(320, 250);
ball[4] = new Ball(440, 190);
ball[5] = new Ball(100, 350);
ball[6] = new Ball(80, 120);
ball[7] = new Ball(130, 240);
/* Player */
var player = new Player();
var score;
/* PLAYER OBJECT */
function Player()
{
/* private member variables */
var x = 10;
var y = 10;
var playerColour = "red";
var width = 25;
var height = 30;
var speed = 10;
/* public methods */
this.draw = draw;
function draw()
{
g.fillStyle = playerColour;
g.fillRect(x, y, width, height);
this.isHit();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getSpeed = getSpeed;
function getSpeed()
{
return speed;
}
this.getW = getW;
function getW()
{
return width;
}
this.getH = getH;
function getH()
{
return height;
}
this.isHit = isHit;
function isHit()
{
for (var i = 0; i < ball.length; i++)
{
if (((x + width) >= ball[i].getX()) && ((x + width) <= (ball[i].getX() + (ball[i].getRadius() * 2)))
&& ((y + height) >= ball[i].getY()) && ((y + height) <= (ball[i].getY() + (ball[i].getRadius() * 2))))
{
clearInterval(theInterval);
drawFinalScore();
//alert("GAME OVER");
console.log("game over");
}
}
}
}
/* BALL OBJECT */
function Ball(newX, newY)
{
var x = newX;
var y = newY;
var dx = 2;
var dy = 4;
var radius = 10;
var targetColour = "blue";
/* public methods */
this.draw = draw;
function draw()
{
g.beginPath();
g.fillStyle = targetColour;
g.arc(x, y, radius, 0, Math.PI * 2);
g.fill();
g.closePath();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getRadius = getRadius;
function getRadius()
{
return radius;
}
this.move = move;
function move()
{
x += dx;
y += dy;
// Bounce on a left or right edge.
if (x + dx > canvas.width - radius || x + dx < radius)
{
dx = -dx;
}
// If ball hits the top, bounce it.
else if (y + dy < radius)
{
dy = -dy;
}
//If the ball hits the bottom, check see if it hits a paddle.
else if (y + dy > canvas.height - radius)
{
dy = -dy;
}
}
}
/* MAIN GAME */
function playGame()
{
g.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas at start.
player.draw();
for (var i = 0; i < 8; i++)
{
ball[i].move();
ball[i].draw();
}
// draw the score
drawElapsedTime();
}
/* SCORE */
var startTime;
// ending elapsed time in seconds
var score;
function drawElapsedTime(){
var elapsed=parseInt((new Date() - startTime)/1000);
g.save();
g.beginPath();
g.fillStyle="red";
g.font="14px Verdana"
// draw the running time at half opacity
g.globalAlpha=0.50;
g.fillText(elapsed+" secs",canvas.width-75,25);
g.restore();
}
function drawFinalScore(){
// set the final score just once
if(score==null){ score=parseInt((new Date() - startTime)/1000); }
g.save();
g.beginPath();
g.fillStyle="red";
g.font="30px Verdana"
g.fillText("Game Over: "+score+" secs",50,35);
g.restore();
}
function arrowKeyDown(e)
{
var stepSize = 10; //Increase size
if (e.keyCode == 37) // left
{
player.setX(player.getX() - player.getSpeed());
if (player.getX() < 0)
{
player.setX(0);
}
}
else if(e.keyCode == 38) // up
{
player.setY(player.getY() - player.getSpeed());
if (player.getY() < 0)
{
player.setY(0);
}
}
else if(e.keyCode == 39) // right
{
player.setX(player.getX() + player.getSpeed());
if ((player.getX() + player.getW()) > canvas.width)
{
player.setX(canvas.width - player.getW());
}
}
else if(e.keyCode == 40) // down
{
player.setY(player.getY() + player.getSpeed());
if ((player.getY() + player.getH()) > canvas.height)
{
player.setY(canvas.height - player.getH());
}
}
}
document.addEventListener('keydown',arrowKeyDown);
</script>
</head>
<body>
<h1>A V O I D</h1>
<canvas id="simpleCanvas"></canvas>
<script>
/* Get the canvas id */
var canvas = document.getElementById("simpleCanvas");
/* Give the canvas a width and height */
/* The width and height are in canvas logical units */
canvas.width = 500;
canvas.height = 500;
/* Assign a graphics context to the canvas, so that we can draw on it */
var g = canvas.getContext("2d");
/* Do the function, call every 20 milliseconds*/
startTime=new Date();
var theInterval=setInterval(playGame, 20);
</script>
<audio src="intense.mp3" autoplay loop></audio>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<h1>
A V O I D
</h1>
<style>
body
{
background-color:green;
}
#simpleCanvas
{
position: absolute;
top: 20%;
left: 30%;
border:2px solid blue;
width:500px;
height:500px;
background-color: yellow;
}
}
</style>
<script>
/* Ball Array */
enter code here`var ball = new Array();
ball[0] = new Ball(150, 150); // x location of target, y location of target
ball[1] = new Ball(200, 350);
ball[2] = new Ball(400, 350);
ball[3] = new Ball(320, 250);
ball[4] = new Ball(440, 190);
ball[5] = new Ball(100, 350);
ball[6] = new Ball(80, 120);
ball[7] = new Ball(130, 240);
/* Player */
var player = new Player();
var score;
/* PLAYER OBJECT */
function Player()
{
/* private member variables */
var x = 10;
var y = 10;
var playerColour = "red";
var width = 25;
var height = 30;
var speed = 10;
/* public methods */
this.draw = draw;
function draw()
{
g.fillStyle = playerColour;
g.fillRect(x, y, width, height);
this.isHit();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getSpeed = getSpeed;
function getSpeed()
{
return speed;
}
this.getW = getW;
function getW()
{
return width;
}
this.getH = getH;
function getH()
{
return height;
}
this.isHit = isHit;
function isHit()
{
for (var i = 0; i < ball.length; i++)
{
if (((x + width) >= ball[i].getX()) && ((x + width) <= (ball[i].getX() + (ball[i].getRadius() * 2)))
&& ((y + height) >= ball[i].getY()) && ((y + height) <= (ball[i].getY() + (ball[i].getRadius() * 2))))
{
alert("GAME OVER");
}
}
}
}
/* BALL OBJECT */
function Ball(newX, newY)
{
var x = newX;
var y = newY;
var dx = 2;
var dy = 4;
var radius = 10;
var targetColour = "blue";
/* public methods */
this.draw = draw;
function draw()
{
g.beginPath();
g.fillStyle = targetColour;
g.arc(x, y, radius, 0, Math.PI * 2);
g.fill();
g.closePath();
}
this.setX = setX;
function setX(newX)
{
x = newX;
}
this.getX = getX;
function getX()
{
return x;
}
this.setY = setY;
function setY(newY)
{
y = newY;
}
this.getY = getY;
function getY()
{
return y;
}
this.getRadius = getRadius;
function getRadius()
{
return radius;
}
this.move = move;
function move()
{
x += dx;
y += dy;
// Bounce on a left or right edge.
if (x + dx > canvas.width - radius || x + dx < radius)
{
dx = -dx;
}
// If ball hits the top, bounce it.
else if (y + dy < radius)
{
dy = -dy;
}
//If the ball hits the bottom, check see if it hits a paddle.
else if (y + dy > canvas.height - radius)
{
dy = -dy;
}
}
}
/* MAIN GAME */
function playGame()
{
g.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas at start.
player.draw();
for (var i = 0; i < 8; i++)
{
ball[i].move();
ball[i].draw();
}
}
/* SCORE */
var isGameOver=false;
var startTime;
// ending elapsed time in seconds
var score;
function drawElapsedTime(){
var elapsed=parseInt((new Date() - startTime)/1000);
ctx.save();
ctx.beginPath();
ctx.fillStyle="red";
ctx.font="14px Verdana"
// draw the running time at half opacity
ctx.globalAlpha=0.50;
ctx.fillText(elapsed+" secs",canvas.width-75,25);
ctx.restore();
}
function drawFinalScore(){
// set the final score just once
if(score==null){ score=parseInt((new Date() - startTime)/1000); }
ctx.save();
ctx.beginPath();
ctx.fillStyle="red";
ctx.font="18px Verdana"
ctx.fillText("Game Over: "+score+" secs",20,25);
ctx.restore();
}
function arrowKeyDown(e)
{
var stepSize = 10; //Increase size
if (e.keyCode == 37) // left
{
player.setX(player.getX() - player.getSpeed());
if (player.getX() < 0)
{
player.setX(0);
}
}
else if(e.keyCode == 38) // up
{
player.setY(player.getY() - player.getSpeed());
if (player.getY() < 0)
{
player.setY(0);
}
}
else if(e.keyCode == 39) // right
{
player.setX(player.getX() + player.getSpeed());
if ((player.getX() + player.getW()) > canvas.width)
{
player.setX(canvas.width - player.getW());
}
}
else if(e.keyCode == 40) // down
{
player.setY(player.getY() + player.getSpeed());
if ((player.getY() + player.getH()) > canvas.height)
{
player.setY(canvas.height - player.getH());
}
}
}
document.addEventListener('keydown',arrowKeyDown);
</script>
</head>
<body>
<canvas id="simpleCanvas">
Your browser does not support the HTML5 <canvas> tag.
</canvas>
<script>
/* Get the canvas id */
var canvas = document.getElementById("simpleCanvas");
/* Give the canvas a width and height */
/* The width and height are in canvas logical units */
canvas.width = 500;
canvas.height = 500;
/* Assign a graphics context to the canvas, so that we can draw on it */
var g = canvas.getContext("2d");
/* Do the function, call every 20 milliseconds*/
setInterval(playGame, 20);
</script>
<audio src="intense.mp3" autoplay loop></audio>
</body>
</html>
/*This is my code and i tryed adding it in and making it function but it would not work ? Dont know what im doing wrong ? Thanks for the reply
I'm creating a survival zombie game and when the zombie is close to the player the player can attack the zombie. How can I create a line of sight of the player and if the zombie is in a specific radius and angle of the player (Basically close to the player) then the player can attack. I manage to work out the player facing forward but how can i create the angle like +- 15 from the way the player is facing and if the zombies are within the radius and angle of the player. So far this is what I have done
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import flash.display.Graphics;
public class Player extends MovieClip
{
//Player Setting
var walkSpeed:Number = 4;
var walkRight:Boolean = false;
var walkLeft:Boolean = false;
var walkUp:Boolean = false;
var walkDown:Boolean = false;
var attacking:Boolean = false;
var radius:Number = 60;
public function Player()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,walk);
addEventListener(Event.ENTER_FRAME,Update);
stage.addEventListener(KeyboardEvent.KEY_UP,stopWalk);
stage.addEventListener(MouseEvent.CLICK,attack);
}
function walk(event:KeyboardEvent)
{
//When Key is Down
if (event.keyCode == 68)
{
walkRight = true;
}
if (event.keyCode == 87)
{
walkUp = true;
}
if (event.keyCode == 65)
{
walkLeft = true;
}
if (event.keyCode == 83)
{
walkDown = true;
}
}
function Update(event:Event)
{
//if attacking is true then key moves are false;
if ((attacking == true))
{
walkRight = false;
walkLeft = false;
walkUp = false;
walkDown = false;
}
else if ((attacking == false))
{
//Else if attacking is false then move and rotate to mouse;
var dx = parent.mouseX - x;
var dy = parent.mouseY - y;
var angle = Math.atan2(dy,dx) / Math.PI * 180;
rotation = angle;
var radiusx:Number = x+radius*Math.cos(rotation/180*Math.PI);
var radiusy:Number = y+radius*Math.sin(rotation/180*Math.PI);
if ((walkRight == true))
{
x += walkSpeed;
gotoAndStop(2);
}
if ((walkUp == true))
{
y -= walkSpeed;
gotoAndStop(2);
}
if ((walkLeft == true))
{
x -= walkSpeed;
gotoAndStop(2);
}
if ((walkDown == true))
{
y += walkSpeed;
gotoAndStop(2);
}
}
}
//Calculate the distance between the two
public function distanceBetween(player:Object,zombies:Object):Number
{
var dx:Number = player.x - zombies.x;
var dy:Number = player.y - zombies.y;
return Math.sqrt(((dx * dx) + dy * dy));
}
function stopWalk(event:KeyboardEvent)
{
if ((attacking == false))
{
if (event.keyCode == 68)
{
event.keyCode = 0;
walkRight = false;
gotoAndStop(1);
}
if (event.keyCode == 87)
{
event.keyCode = 0;
walkUp = false;
gotoAndStop(1);
}
if (event.keyCode == 65)
{
event.keyCode = 0;
walkLeft = false;
gotoAndStop(1);
}
if (event.keyCode == 83)
{
event.keyCode = 0;
walkDown = false;
gotoAndStop(1);
}
}
}
function attack(event:MouseEvent)
{
if ((attacking == false))
{
attacking = true;
gotoAndStop(3);
if (hitTestObject(MovieClip(root).Zo))
{
trace('ouch');
}
}
}
}
}
In psuedo code, here's one way you could do this :
// check distance between player and zombie
// if zombie is close enough
//get angle between player and zombie
//check difference between player facing and angle
//if difference between angle <= 15 degrees
//attack zombie
Here is a function that will return the angle from your player to a given target :
// I used the code from your code above to create this function
function getAngle(targetX:Number, targetY:Number):Number
{
var dx = targetX - player.x;
var dy = targetY - player.y;
var angle = Math.atan2(dy,dx) / Math.PI * 180;
return angle;
}
This is the distance function in your code, that I modified to accept a movieclips :
public function distanceBetween(player:MovieClip,zombie:MovieClip):Number
{
var dx:Number = player.x - zombie.x;
var dy:Number = player.y - zombie.y;
return Math.sqrt(((dx * dx) + dy * dy));
}
So you could use the psuedo code above to create code to solve your problem :
// check distance between player and zombie
if (distanceBetween(player,zombie) <= maxRadius)
{
// get angle between player and zombie
var angleToZombie:Number = getAngle(zombie.x, zombie.y);
// I am assuming that the facing is going to be towards the mouse
// calculate facing of player
var currentFacing:Number = getAngle(mouseX, mouseY);
//check difference between player facing and angle
if (Math.abs(currentFacing - angleToZombie) <= 15)
{
// attack the zombie
}
}