how to prevent overlapping of 2 components - javascript

how to prevent overlapping of 2 components, please help me to make them follow Mouse but not overlap. i am not expert in coding, please explain in simple language.
function component(x,y,r) {
var randomcolor = ["violet","indigo","blue","green","yellow","orange","red"];
this.pos=createVector(x,y);
this.r=r;
this.color=randomcolor[Math.floor(Math.random()*randomcolor.length)];
this.show=function() {
fill(this.color);
stroke(241,241,241);
ellipse(this.pos.x,this.pos.y,this.r*2,this.r*2);
}
this.crash = function(other) {
var d = p5.Vector.dist(this.pos,other.pos);
if (d<this.r+other.r) {
this.r+=other.r/20;
return true;}
}
this.move=function(){
this.pos.x=lerp(this.pos.x,mouseX,0.1);
this.pos.y=lerp(this.pos.y,mouseY,0.1);
this.pos.x = constrain(this.pos.x,this.r,width-this.r)
this.pos.y = constrain(this.pos.y,this.r,height-this.r)
}
}

To make multiple objects move without running into each other you will need to
keep track of the current location of all objects
be able to identify each object so that the collision method does not detect a collision of an object with itself
check to make sure there will not be a collision before attempting to move an object
For your example code this is one possibility for making multiple components move towards the mouse without running into each other. I rewrote your crash function and added some global variables. This is not elegant but I think it answers your question in a way that you can understand how this kind of problem can be approached.
var ids = 0;
var allComponents = [];
function setup(){
createCanvas(600,600);
new component(10,10,10);
new component(590,10,10);
}
function draw(){
background(255);
for (let i = 0; i < allComponents.length; i++){
allComponents[i].show();
allComponents[i].move();
}
}
function component(x,y,r) {
var randomcolor = ["violet","indigo","blue","green","yellow","orange","red"];
this.pos=createVector(x,y);
this.r=r;
this.id = ids++;
allComponents[allComponents.length] = this;
this.color=randomcolor[Math.floor(Math.random()*randomcolor.length)];
this.show=function() {
fill(this.color);
stroke(241,241,241);
ellipse(this.pos.x,this.pos.y,this.r*2,this.r*2);
}
this.crash = function(other) {
var d = p5.Vector.dist(this.pos,other.pos);
if (d< this.r + other.r) {
return true;
}
return false;
}
this.move=function(){
let originalX = this.pos.x;
let originalY = this.pos.y;
this.pos.x=lerp(this.pos.x,mouseX,0.1);
this.pos.y=lerp(this.pos.y,mouseY,0.1);
this.pos.x = constrain(this.pos.x,this.r,width-this.r);
this.pos.y = constrain(this.pos.y,this.r,height-this.r);
for (let i = 0; i < allComponents.length; i++){
let other = allComponents[i];
if (this.id !== other.id && this.crash(other)){
this.pos.x = originalX;
this.pos.y = originalY;
break;
}
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>

Related

JS Game - cannot set property of undefined typeerror

I know there are similar questions as mine but they did not work for my case and I can not waste more time.
I am learning JS so I am trying to code an easy pacman game. In this case, every time pacman eats a powerup, all the active ghosts have to turn into weak ghosts.
The problems comes when while I am playing and I grab a powerup, the game crashes saying:
Uncaught TypeError: Cannot set property 'isWeak' of undefined.
I did not post all the code in this question. Only the main part where the error comes from(I think so).
My code in main.js:
var activeGhosts = [];
var powerups = [];
for (var i = 0; i < powerups.length; i++) {
if (pacman.collision(powerups[i])) {
makeWeak();
powerups.splice(i,1);
}
}
function makeWeak() {
for (var i = 0; i < activeGhosts.length; i++) activeGhosts[i].isWeak = true;
}
My code in ghost.js:
function Ghost(x,y,img){
this.x = x;
this.y = y;
this.img = img;
this.direction = 0;
this.radius = 16; // half of 32 px because every image is 32x32 px
this.crash = false;
this.isWeak = false;
this.show = function () {
if (this.isWeak) {
image(weakghostimg, this.x, this.y);
} else {
// img can be the all the different ghosts
image(img, this.x, this.y);
}
};

Type Error - Referencing Javascript Classes

Firstly a little elaboration of the project I'm working on. I have started building a 'map maker' for a 2d game I am working on. The project is just for fun and has proven so far to be a great way to learn new things.
I recently showed my working map maker code to a friend who suggested it would be much more re-usable if I restructured the project to be more OOR, which I am now attempting.
The problem I have is when I add a 'Guild' instance to my map, the first one works fine, but the second causes a type error that is giving me a headache!
I will post all of the relevant code from the different files below, but the overall structure is as follows:
Map.js = Map class file, container for setting the map overall size and iterating over (and placing) map objects.
MapObject.js = Class file for simple map objects such as walls, contains the position and icon properties.
Guild.js = Class file, extends MapObject.js, this is where my problem seems to be, adds an additional 'MapIcon' and will have other features such as levels and names etc.
map-maker.js = Main file for generating the map-maker page, utilises the above class files to create the map.
Below is the code used to create an instance of 'Guild' on my map:
map-maker.js (creating the map / map object / guild instances)
// Initialise a new instance of map class from Map.js using the user
provided values for #mapX and #mapY.
var currentMap = new Map(XY,40);
// Get the user box volume * map boxsize from Map.js
currentMap.calcDimensions();
// Create a Map Object and push it to the currentMap with its position.
function createMapObject(x,y,floor){
currentMap.objects.push(new MapObject(x,y,floor));
}
// Create a Guild Object (extension of Map Object) and push it to the currentMap with its position.
function createGuildObject(x,y,floor){
currentMap.objects.push(new Guild(x,y,floor));
}
....
case 13: // Enter Key (Submit)
unhighlightTools();
currentMap.drawMap();
if(currentFloor != null){
currentFloor.hasFloor = true;
if(currentFloor.tileName == "Guild"){
createGuildObject(currentFloor.position.x,currentFloor.position.y,currentFloor);
}else {
createMapObject(currentFloor.position.x,currentFloor.position.y,currentFloor);
}
console.log("Map object created at - X:"+currentFloor.position.x+" Y:"+currentFloor.position.y);
}
currentFloor = [];
highlightTools();
break;
}
Guild.js (constructor and assigning map icon)
class Guild extends MapObject {
constructor(x,y,floor) {
super(x,y,floor);
this.levels = [];
}
mapIcon() {
this.mapIcon = new Image();
this.mapIcon.src = "../images/mapSprites/obj-1.png"
return this.mapIcon;
}
}
MapObject.js (position setup and constructor)
class MapObject {
constructor(x,y,floor) {
this.position = {x, y};
this.icon = this.wallFloorIcons(floor);
}
wallFloorIcons(floor) {
this.img = new Image();
this.name = "";
this.name += (floor.wallNorth) ? 'n' : '';
this.name += (floor.wallEast) ? 'e' : '';
this.name += (floor.wallSouth) ? 's' : '';
this.name += (floor.wallWest) ? 'w' : '';
this.name = 'wall-'+this.name+'.png';
if(this.name == 'wall-.png'){
this.img.src = "../images/mapSprites/floor.png";
}else {
this.img.src = "../images/mapSprites/"+this.name;
}
return this.img;
}
getIcon() {
return this.img;
}
}
Map.js (processing the objects at a given location and drawing the canvas)
class Map {
// Map Width / Height and number of boxes. Used to generate map and zoom level.
constructor(wh, boxSize) {
this.size = wh;
this.width = wh[0];
this.height = wh[1];
this.boxSize = boxSize;
this.objects = [];
this.boxes = wh[0];
}
// Calculates the width and height * boxSize for rendering the canvas.
calcDimensions(){
this.realX = Math.floor(this.width * this.boxSize);
this.realY = Math.floor(this.height * this.boxSize);
this.realX = parseInt(this.realX,10);
this.realY = parseInt(this.realY,10);
this.realXY = [
this.realX,
this.realY
];
return this.realXY;
}
// Draws the canvas, grid and adds the objects that belong to the map.
drawMap(){
var self = this;
self.canvas = document.getElementById("canvas");
self.c = self.canvas.getContext("2d");
self.background = new Image();
self.background.src = "../images/mapSprites/oldPaperTexture.jpg";
// Make sure the image is loaded first otherwise nothing will draw.
self.background.onload = function(){
self.c.drawImage(self.background,0,0);
self.fillMap();
}
}
fillMap(){
var self = this;
self.c.lineWidth = 1;
self.c.strokeStyle = 'black';
self.c.fillStyle = "rgba(255, 255, 255, 0.2)";
for (var row = 0; row < self.boxes; row++) {
for (var column = 0; column < self.boxes; column++) {
var x = column * self.boxSize;
var y = row * self.boxSize;
self.c.beginPath();
self.c.rect(x, y, self.boxSize, self.boxSize);
self.c.stroke();
self.c.closePath();
for (var i=0; i<self.objects.length; i++) {
var floor = self.objects[i];
if (floor.position.x == column && floor.position.y == row) {
if (self.objectsAtPosition({x:floor.position.x, y:floor.position.y}) != null) {
var mapObjects = self.objectsAtPosition({x:floor.position.x, y:floor.position.y})
for (var mapObject of mapObjects) {
this.c.drawImage(mapObject.getIcon(), x, y, self.boxSize, self.boxSize);
console.log(mapObject);
if(mapObject instanceof Guild){
console.log(mapObject);
this.c.drawImage(mapObject.mapIcon(), x, y, self.boxSize, self.boxSize);
}
}
}
}
}
}
}
}
deleteObject(pos){
this.objectsAtPosition(pos);
for( var i = 0; i < this.objects.length; i++){
if(this.objects[i] == this.objs){
delete this.objects[i];
this.objects.splice(i,1);
}
}
}
objectsAtPosition(position) {
var objs = [];
for (var o of this.objects) {
if (o.position.x == position.x && o.position.y == position.y) {
objs.push(o);
}
}
return objs;
}
}
When I run the code, this is my error:
Uncaught TypeError: mapObject.mapIcon is not a function
at Map.fillMap (Map.js:70)
at Image.self.background.onload (Map.js:39)
The error comes after I add 1 guild then try to add any other map object. Guild or otherwise.
Sorry if this question is a little vague, I'm still learning (as you can see :p).
Thanks for your time!
Earl Lemongrab
Got a solution from a friend in the end.
The issue was that I was reassigning this.mapIcon = new Image() so it exploded when it was called a second time.
Feel pretty silly for not spotting it.
Thanks for the help everyone.

Phaser P2 physics. How to kill a bullet(sprite) in a group on collision with another collision group

I'm quite new to javaScript and programing in general and i'm trying to make a one vs one 2D tank game using Phaser API.
I have been stuck for the past two days trying to figure out how to kill a single bullet that hits the other tank. I did manage to get it to work using the arcade physics and by using the Phaser example tank game. But i can't seem to convert my knowlegde so far and apply it to the P2 physics which i am currently using and would like to stick to.
This is the tank constructor which i use to create two tanks, each tank holds its individual bulletGroup named bullets, at the far bottom i have a function called shoot which reset a bullet and make it fly towards the target (this particular function is mostly taken from the phaser tank example)
var tank = function(playerIndex, startX, startY, facing, keyLeft, keyRight, keyUp, keyDown, keyTLeft, keyTRight, keyShoot) {
this.playerIndex = playerIndex.toString();;
this.tankBody;
this.tankTurret;
this.facing = facing;
this.bullets;
this.fireRate = 200;
this.nextFire = 0;
this.health = 100;
this.isAlive = true;
this.bodyTurnSpeed = 2;
this.turretTurnSpeed = 2;
this.currentSpeed = 0;
this.maxSpeed = 50;
this.keyLeft = keyLeft;
this.keyRight = keyRight;
this.keyUp = keyUp;
this.keyDown = keyDown;
this.keyTLeft = keyTLeft;
this.keyTRight = keyTRight;
this.keyShoot = keyShoot;
this.create = function() {
if (this.playerIndex === "1") {
this.tankBody = game.add.sprite(startX, startY, "body_player_one");
this.tankTurret = game.add.sprite(startX, startY, "turret_player_one");
} else if (this.playerIndex === "2") {
this.tankBody = game.add.sprite(startX, startY, "body_player_two");
this.tankTurret = game.add.sprite(startX, startY, "turret_player_two");
}
this.tankBody.anchor.setTo(0.5, 0.5);
this.tankTurret.anchor.setTo(0.5, 0.5);
game.physics.p2.enable([this.tankBody]);
this.tankBody.body.immovable = false;
this.tankBody.body.collideWorldBounds = true;
this.tankBody.body.debug = false;
this.tankBody.body.fixedRotation = true;
this.tankBody.body.mass = 50;
// this.tankBody.body.kinematic = true;
this.bullets = game.add.group();
this.bullets.enableBody = true;
this.bullets.physicsBodyType = Phaser.Physics.P2JS;
this.bullets.createMultiple(100, 'bullet', 0, false);
this.bullets.setAll('anchor.x', 0.5);
this.bullets.setAll('anchor.y', 0.5);
this.bullets.setAll('outOfBoundsKill', true);
this.bullets.setAll('checkWorldBounds', true);
switch (this.facing) {
case "left":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(-90);
this.tankTurret.rotation = Phaser.Math.degToRad(-90);
break;
case "right":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(90);
this.tankTurret.rotation = Phaser.Math.degToRad(90);
break;
case "up":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(0);
this.tankTurret.rotation = Phaser.Math.degToRad(0);
break;
case "down":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(180);
this.tankTurret.rotation = Phaser.Math.degToRad(180);
break;
}
}
this.update = function() {
if (this.isAlive) {
if (game.input.keyboard.isDown(this.keyLeft)) {
this.tankBody.rotation = this.tankBody.body.rotation -= Phaser.Math.degToRad(this.bodyTurnSpeed);
}
if (game.input.keyboard.isDown(this.keyRight)) {
this.tankBody.rotation = this.tankBody.body.rotation += Phaser.Math.degToRad(this.bodyTurnSpeed);;
}
if (game.input.keyboard.isDown(this.keyUp)) {
this.tankBody.body.moveForward(50);
} else if (game.input.keyboard.isDown(this.keyDown)) {
this.tankBody.body.moveBackward(50);
} else this.tankBody.body.setZeroVelocity();
if (game.input.keyboard.isDown(this.keyTLeft)) {
this.tankTurret.rotation -= Phaser.Math.degToRad(this.turretTurnSpeed);
} else if (game.input.keyboard.isDown(this.keyTRight)) {
this.tankTurret.rotation += Phaser.Math.degToRad(this.turretTurnSpeed);
}
if (game.input.keyboard.isDown(this.keyShoot)) {
this.shoot();
}
this.tankTurret.x = this.tankBody.x;
this.tankTurret.y = this.tankBody.y;
} else {
this.tankTurret.kill();
this.tankBody.kill();
}
}
this.shoot = function() {
if (game.time.now > this.nextFire && this.bullets.countDead() > 0) {
this.nextFire = game.time.now + this.fireRate;
var bullet = this.bullets.getFirstExists(false);
bullet.reset(this.tankTurret.x + this.tankTurret.width / 2 * Math.cos(this.tankTurret.rotation - Phaser.Math.degToRad(90)),
this.tankTurret.y + this.tankTurret.width / 2 * Math.sin(this.tankTurret.rotation - Phaser.Math.degToRad(90)));
bullet.body.rotation = this.tankTurret.rotation;
bullet.body.mass = 100;
bullet.body.moveForward(500);
}
}
}
This is where i assign collisionGroups and make them collide with eachother,
everything here is working as intended but the bullets do not dissapear
function create() {
game.add.sprite(0, 0, "background_one");
game.physics.startSystem(Phaser.Physics.P2JS);
game.physics.p2.setImpactEvents(true);
//creating the collisiongroups
var bulletsCollisionGroup = game.physics.p2.createCollisionGroup();
var playerOneCollisionGroup = game.physics.p2.createCollisionGroup();
var playerTwoCollisionGroup = game.physics.p2.createCollisionGroup();
var wallCollisionGroup = game.physics.p2.createCollisionGroup();
//sets the objects to collide with gamestage borders (prevent objects from moving out of bounds)
game.physics.p2.updateBoundsCollisionGroup();
//creating players, each player holds its own bulletgroup
player_one.create();
player_two.create();
//creates the tiles (mouseclick to place)
createTiles();
//sets sprites to different collisiongroups
player_one.tankBody.body.setCollisionGroup(playerOneCollisionGroup);
for (var i = 0; i < player_one.bullets.children.length; i++) //player_one bullets
{
player_one.bullets.children[i].body.setCollisionGroup(bulletsCollisionGroup);
}
player_two.tankBody.body.setCollisionGroup(playerTwoCollisionGroup);
for (var i = 0; i < player_two.bullets.children.length; i++) //player_two bullets
{
player_two.bullets.children[i].body.setCollisionGroup(bulletsCollisionGroup);
}
for (var i = 0; i < tiles.children.length; i++) //tiles
{
tiles.children[i].body.setCollisionGroup(wallCollisionGroup);
}
//makes the collisiongroups collide with eachother
player_one.tankBody.body.collides([playerTwoCollisionGroup, wallCollisionGroup, bulletsCollisionGroup]);
player_two.tankBody.body.collides([playerOneCollisionGroup, wallCollisionGroup, bulletsCollisionGroup]);
for (var i = 0; i < tiles.children.length; i++) //tiles with everything
{
tiles.children[i].body.collides([playerOneCollisionGroup, playerTwoCollisionGroup, bulletsCollisionGroup]);
}
for (var i = 0; i < player_one.bullets.children.length; i++) //player_one bullets with everything
{
player_one.bullets.children[i].body.collides([wallCollisionGroup]);
player_one.bullets.children[i].body.collides(playerTwoCollisionGroup, function() {
bulletHitPlayer(player_two)
}, this);
}
for (var i = 0; i < player_two.bullets.children.length; i++) //player_two bullets with everything
{
player_two.bullets.children[i].body.collides([wallCollisionGroup]);
player_two.bullets.children[i].body.collides(playerOneCollisionGroup, function() {
bulletHitPlayer(player_one)
}, this);
}
}
this is the function i tried to use for callback on collision with a tank, it seems to work in arcade physics with overlap
function bulletHitPlayerOne(tank, bullet) {
bullet.kill()
tank.health -= 20;
if (player.health <= 0) {
tank.isAlive = false;
}
}
and this is how i tried to implement the function above to my collisionHandler
for (var i = 0; i < player_two.bullets.children.length; i++) {
player_two.bullets.children[i].body.collides(playerOneCollisionGroup, bulletHitPlayerOne, this);
}
Now, I've tried a various of different ways to solve this problem but im completely stuck, I'm begining to think that i can't kill a sprite in a group with the P2 physics enabled (but then again why wouldn't it work?)
I did seacrh and tried to read as much documentations as possible but with this particular problem i seem to be alone :)
Thank you for your time!
/Martin
Something like this should work.
Game.prototype = {
create: function(){
//...
var bulletsCollisionGroup = game.physics.p2.createCollisionGroup();
var playerOneCollisionGroup = game.physics.p2.createCollisionGroup();
//....
this.bullets = game.add.group();
this.bullets.enableBody = true;
this.bullets.physicsBodyType = Phaser.Physics.P2JS;
this.bullets.createMultiple(100, 'bullet', 0, false);
this.bullets.setAll('anchor.x', 0.5);
this.bullets.setAll('anchor.y', 0.5);
this.bullets.setAll('outOfBoundsKill', true);
this.bullets.setAll('checkWorldBounds', true);
this.bullets.forEach(function(bullet){
bullet.body.setCollisionGroup(bulletsCollisionGroup);
bullet.body.collides(playerOneCollisionGroup);
});
player.body.setCollisionGroup(playerOneCollisionGroup);
player.body.collides(bulletsCollisionGroup, this.hit, this);
},
/...
hit: function(player,bullet){
bullet.parent.sprite.kill();
}
}
Bear in mind that player will collide with the bullet and it will change velocity, acceleration and other properties before the bullet is killed. You may want to use onBeginContact or maybe BroadphaseCallback

My javascript canvas map script and poor performance

Basically below is my script for a prototype which uses 128x128 tiles to draw a map on a canvas which user can drag to move around.
Script does work. However I have a few problems to be solved:
1. Poor performance and I can't figure out why.
2. I am missing a method to buffer the tiles before the actual drawing.
3. If you notice any other issues also that could help me to make things run more smoothly it would be fantastic.
Some explanations for the script:
variables
coordinates - Defines the actual images to be displayed. Image file names are type of '0_1.jpg', where 0 is Y and 1 is X.
mouse_position - As name says, is keeping record of mouse position.
position - This is a poorly named variable. It defines the position of the context drawn on canvas. This changes when user drags the view.
Any assistance would be appreciated greatly. Thank you.
var coordinates = [0, 0];
var mouse_position = [0, 0];
var position = [-128, -128];
var canvas = document.getElementById('map_canvas');
var context = canvas.getContext('2d');
var buffer = [];
var buffer_x = Math.floor(window.innerWidth/128)+4;
var buffer_y = Math.floor(window.innerHeight/128)+4;
var animation_frame_request = function() {
var a = window.requestAnimationFrame;
var b = window.webkitRequestAnimationFrame;
var c = window.mozRequestAnimationFrame;
var d = function(callback) {
window.setTimeout(callback, 1000/60);
}
return a || b || c || d;
}
var resizeCanvas = function() {
window.canvas.width = window.innerWidth;
window.canvas.height = window.innerHeight;
window.buffer_x = Math.floor(window.innerWidth/128)+4;
window.buffer_y = Math.floor(window.innerHeight/128)+4;
window.buffer = [];
for (row = 0; row < window.buffer_y; row++) {
x = [];
for (col = 0; col < window.buffer_x; col++) {
x.push(new Image());
}
window.buffer.push(x);
}
}
var render = function() {
animation_frame_request(render);
for (row = 0; row < window.buffer_y; row++) {
for (col = 0; col < window.buffer_x; col++) {
cy = window.coordinates[1]+row;
cx = window.coordinates[0]+col;
window.buffer[row][col].src = 'map/'+cy+'_'+cx+'.jpg';
}
}
for (row = 0; row < window.buffer_y; row++) {
for (col = 0; col < window.buffer_x; col++) {
window.context.drawImage(window.buffer[row][col],
window.position[0]+col*128,
window.position[1]+row*128, 128, 128);
}
}
}
var events = function() {
window.canvas.onmousemove = function(e) {
if (e['buttons'] == 1) {
window.position[0] += (e.clientX-window.mouse_position[0]);
window.position[1] += (e.clientY-window.mouse_position[1]);
if (window.position[0] >= 0) {
window.position[0] = -128;
window.coordinates[0] -= 1;
} else if (window.position[0] < -128) {
window.position[0] = 0;
window.coordinates[0] += 1;
}
if (window.position[1] >= 0) {
window.position[1] = -128;
window.coordinates[1] -= 1;
} else if (window.position[1] < -128) {
window.position[1] = 0;
window.coordinates[1] += 1;
}
render();
}
window.mouse_position[0] = e.clientX;
window.mouse_position[1] = e.clientY;
}
}
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('load', resizeCanvas, false);
window.addEventListener('mousemove', events, false);
resizeCanvas();
To get better performance you should avoid changing the src of img nodes and move them around instead.
A simple way to minimize the number of img nodes handled and modified (except for screen positioning) is to use an LRU (Least Recently Used) cache.
Basically you keep a cache of last say 100 image nodes (they must be enough to cover at least one screen) by using a dictionary mapping the src url to a node object and also keeping them all in a doubly-linked list.
When a tile is required you first check in the cache, and if it's already there just move it to the front of LRU list and move the img coordinates, otherwise create a new node and set the source or, if you already hit the cache limit, reuse the last node in the doubly-linked list instead. In code:
function setTile(x, y, src) {
var t = cache[src];
if (!t) {
if (cache_count == MAXCACHE) {
t = lru_last;
t.prev.next = null;
lru_last = t.prev;
t.prev = t.next = null;
delete cache[t.src]
t.src = src;
t.img.src = src;
cache[t.src] = t;
} else {
t = { prev: null,
next: null,
img: document.createElement("img") };
t.src = src;
t.img.src = src;
t.img.className = "tile";
scr.appendChild(t.img);
cache[t.src] = t;
cache_count += 1;
}
} else {
if (t.prev) t.prev.next = t.next; else lru_first = t.next;
if (t.next) t.next.prev = t.prev; else lru_last = t.prev;
}
t.prev = null; t.next = lru_first;
if (t.next) t.next.prev = t; else lru_last = t;
lru_first = t;
t.img.style.left = x + "px";
t.img.style.top = y + "px";
scr.appendChild(t.img);
}
I'm also always appending the requested tile to the container so that it goes in front of all other existing tiles; this way I don't need to remove old tiles and they're simply left behind.
To update the screen I just iterate over all the tiles I need and request them:
function setView(x0, y0) {
var w = scr.offsetWidth;
var h = scr.offsetHeight;
var iy0 = y0 >> 7;
var ix0 = x0 >> 7;
for (var y=iy0; y*128 < y0+h; y++) {
for (var x=ix0; x*128 < x0+w; x++) {
setTile(x*128-x0, y*128-y0, "tile_" + y + "_" + x + ".jpg");
}
}
}
most of the time the setTile request will just update the x and y coordinates of an existing img tag, without changing anything else. At the same time no more than MAXCACHE image nodes will be present on the screen.
You can see a full working example in
http://raksy.dyndns.org/tiles/tiles.html

I'm trying to stop snow script and clear the page after x seconds

How can I make the snow clear after a certain time. I've tried using variables and the calling a timeout which switches on to false and stops the makesnow() function but that doesn't seem to clear the page at all.
<script language="javascript">
ns6 = document.getElementById;
ns = document.layers;
ie = document.all;
/*******************[AccessCSS]***********************************/
function accessCSS(layerID) { //
if(ns6){ return document.getElementById(layerID).style;} //
else if(ie){ return document.all[layerID].style; } //
else if(ns){ return document.layers[layerID]; } //
}/***********************************************************/
/**************************[move Layer]*************************************/
function move(layer,x,y) { accessCSS(layer).left=x; accessCSS(layer).top = y; }
function browserBredde() {
if (window.innerWidth) return window.innerWidth;
else if (document.body.clientWidth) return document.body.clientWidth;
else return 1024;
}
function browserHoyde() {
if (window.innerHeight) return window.innerHeight;
else if (document.body.clientHeight) return document.body.clientHeight;
else return 800;
}
function makeDiv(objName,parentDiv,w,h,content,x,y,overfl,positionType)
{
// positionType could be 'absolute' or 'relative'
if (parentDiv==null) parentDiv='body';
var oDiv = document.createElement ("DIV");
oDiv.id = objName;
if (w) oDiv.style.width = w;
if (h) oDiv.style.height= h;
if (content) oDiv.innerHTML=content;
if (positionType==null) positionType="absolute";
oDiv.style.position = positionType;
if (x) oDiv.style.left=x; else oDiv.style.left=-2000;
if (y) oDiv.style.top=y; else oDiv.style.top=-2000;
if (overfl) oDiv.style.overflow=overfl; else oDiv.style.overflow="hidden";
eval(' document.'+parentDiv+'.appendChild (oDiv); ');
delete oDiv;
}
var snowC=0;
var x = new Array();
var y = new Array();
var speed = new Array();
var t=0;
var cC = new Array();
var ra = new Array();
function makeSnow() {
x[snowC] = Math.round(Math.random()*(browserBredde()-60));
y[snowC] = 10;
makeDiv("snow"+snowC,"body",32,32,'<img src="http://i693.photobucket.com/albums/vv296/KIBBLESGRAMMY/CAT/Orange-tabby-cat-icon.gif">');
speed[snowC] = Math.round(Math.random()*8)+1;
cC[snowC]=Math.random()*10;
ra[snowC] = Math.random()*7;
snowC++;
}
function moveSnow() {
var r = Math.round(Math.random()*100);
if (r>70 && snowC<20) makeSnow();
for (t=0;t<snowC;t++) {
y[t]+=speed[t];move("snow"+t,x[t],y[t]);
if (y[t]>browserHoyde()-50) {y[t] = 10;x[t] = Math.round(Math.random()*(browserBredde()-60));}
cC[t]+=0.01;
x[t]+=Math.cos(cC[t]*ra[t]);
}
setTimeout('moveSnow()',20);
}
moveSnow();
</script>
makeSnow just adds the snowflakes. Stopping that, as you say, does not clear anything. moveSnow handles the animation, and calls itself at a timeout. If instead of setting a timeout for the next moveSnow each time, you set it up to run in an interval just once, you would have an easier time stopping it.
window.snowAnimation = window.setInterval(moveSnow, 20);
If you add a css class to your snow flakes, it would be easier to target them for deletion.
oDiv.className = 'snowflake';
Then your clear function could look something like:
function clearSnow() {
window.clearTimeout(window.snowAnimation);
var flakes = document.getElementsByTagName('snowflake');
for(var i = 0, l = flakes.length; i < l; i++) {
document.body.removeChild(flakes[i]);
}
}
Timeout doesnt help, it helps you only to stop creating new snowdivs, however if you see makeDiv is the one which creates new divs on to the body, if you clear / display:none the divs which got created on makeDiv i hope it will clear all the divs on the screen.
You need to remove the divs that were created. It might be easier if you give them all some sort of class, like ".snowflake" as you create them (in makeDiv), then start removing them from the dom.
You will have to clear the elements created after the time you wanna stop snow falling.
Following code snippet will help you to clear the elements
if(count < 500){
setTimeout('moveSnow()',20);
}else{
var i = 0;
var elem = document.getElementById('snow'+i);
do{
elem.parentNode.removeChild(elem);
elem = document.getElementById('snow'+ ++i);
}while(elem != null)
}
count++;
you have to create a global variable count.

Categories

Resources