Pixi Tile Wizard Demo (1)
The introduction
This is in learning pixi tiling wizard when the association of a parallax rolling collision detection demo and encountered a problem.
directory
-
Tile elves
1.1 Creation Methods
1.2 the difference between
1.3 offset value
1.4 Texture offset code
-
Parallax scrolling
2.1 Texture accuracy deviation
-
Collision detection
-
demo
-
conclusion
1. Tiling sprites
Jump back to directory
1.1 Creation Methods
Create a pixi tile Sprite
/ / the first
new PIXI.extras.TilingSprite(texture, width, height);
/ / the second
new PIXI.extras.TilingSprite.from(source, width, height);
Copy the code
1.2 the difference between
The first:
Texture by PIXI. Loader. Shared. Get photo texture in resources.
let bgSpr = new PIXI.extras.TilingSprite(PIXI.Loader.shared.resources['bg'].texture, app.renderer.width, app.renderer.height);
Copy the code
The second:
Source can be imported directly through the URL path.
let bgSpr = new PIXI.extras.TilingSprite.from('./img/bg.jpg', app.renderer.width, app.renderer.height);
Copy the code
Note that widht height means that the tiled range is not set. Default is 100px.
1.3 offset value
tilePosition
:
Tileposition. set(x, y) differs from positions. Set (x, y) in that the former moves the tile Sprite texture and the latter moves the tile Sprite position.
Specific usage:
Update tilePosition.x value with ticker game loop.
app.ticker.add(() = > {
bgSpr.tilePosition.x -= -1;
});
Copy the code
1.4 Texture offset code
let app = new PIXI.Application({widht: app.renderer.width, height: app.renderer.height});
document.body.appendChild(app.view);
PIXI.Loader.shared.add('bg'.'./img/bg.jpg');
PIXI.Loader.shared.load(() = > {
setup();
});
function setup () {
let bgSpr = new PIXI.extras,TilingSprite(PIXI.Loader.shared.resources['bg'].texture, app.renderer.width, app.renderer.height);
app.stage.addChild(bgSpr);
app.ticker.add(() = > {
bgSpr.tilePosition.x -= 1;
});
};
Copy the code
Effect drawing (random material) :
2, parallax rolling
Jump back to directory
Tiling sprites are commonly used to create seamless scrolling backgrounds. Above we implemented the offset of tiling sprites. What is parallax scrolling?
Parallax scrolling is a three-dimensional motion effect created by moving multiple layers of background at different speeds. For example, in a Super Mario Game, the movement of the character’s location and the movement of the background sky is a parallax scroll.
This means you need two tile sprites and offset them at different speeds throughout the game loop.
let prospectSpr = new PIXI.extras.TilingSprite(PIXI.Loader.shared.resources['prospect'].texture, app.renderer.width, 437);
app.stage.addChild(prospectSpr);
app.ticker.add(() = > {
prospectSpr.tilePosition.x -= 3;
})
Copy the code
Effect:
A parallax scrolling is achieved, with the speed of the background layer being 1 and the speed of the foreground layer being 3.
2.1 Texture accuracy deviation
In the process of learning, I also encountered a pit, that is, every time I offset a cycle, the clarity of the Sprite map will become a little bit worse, and after multiple cycles, the Sprite map will become a Mosaic:
Note: this does not happen on browser emulation mobile, but only on mobile.
At first I thought there was a problem with the game loop method, but after changing the plugin, the above situation still appeared in the test results. I also found a similar situation in Google:
Probably the problem is that tile sprites have accuracy issues over time.
Solutions are also proposed:
prospectSpr.tilePosition.x %= PIXI.Loader.shared.resources['prospect'].texture.width;
Copy the code
The ticker code is as follows:
app.ticker.add(() = > {
prospectSpr.tilePosition.x -= 3;
prospectSpr.tilePosition.x %= PIXI.Loader.shared.resources['prospect'].texture.width;
})
Copy the code
3. Collision detection
Jump back to directory
The principle of collision detection in web pages is to calculate whether two rectangles collide by x and y coordinates, that is, to determine whether they overlap.
The collision detection method can be found in the PIXI tutorial. There is also a handy plugin called bump.js, which is very simple to use:
b.hit(sprite1, sprite2); // Returns a Boolean type, true for collision.B.h it (sprite1, sprite2,true); // The third argument is true and does not overlap on collisions.B.h it (sprite1, sprite2,true.true); // The fourth argument is true and bounces the first Sprite on collision
Copy the code
For a full tutorial, go to: Bump.js Tutorial.
Knowing the principle, it is actually very simple to do, as long as the center point of the wizard is set, and the x and y axes of the two sprites are judged to overlap. The following is a relatively simple collision detection that I have implemented:
function bump (spr1, spr2) {
spr1.anchor.set(0.5.1); // Set the Sprite center position
spr2.anchor.set(0.5.1);
if (spr1.x - spr2.x < spr2.width && spr1.x - spr2.x > -spr2.width) {
// Meet the x position condition
return spr1.y - spr2.y === 0? true : false; // Return if y conditions are met
} else {
return false; }}Copy the code
Then you just have to determine whether the return is true or false.
New code:
PIXI.Loader.shared
.add('role'.'./img/sprite1_0.png')
.add('monster'.'./img/blob.png');let role = new PIXI.Sprite(PIXI.Loader.shared.resources['role'].texture);
let monster = new PIXI.Sprite(PIXI.Loader.shared.resources['monster'].texture);
let isBump = null;
role.anchor.set(0.5.1);
monster.anchor.set(0.5.1);
role.scale.set(1.5.1.5);
monster.scale.set(3.3);
role.position.set(300, app.renderer.height - 180);
monster.position.set(1500, app.renderer.height - 180);
app.stage.addChild(role, monster);
app.ticker.add(() = > {
monster.x -= 3;
bump(role, monster) && console.log('collision');
});
function bump (spr1, spr2) {
spr1.anchor.set(0.5.1); // Set the Sprite center position
spr2.anchor.set(0.5.1);
if (spr1.x - spr2.x < spr2.width && spr1.x - spr2.x > -spr2.width) {
// Meet the x position condition
return spr1.y - spr2.y === 0? true : false; // Return if y conditions are met
} else {
return false; }}Copy the code
Effect:
4, the demo
Jump back to directory
The above main function is almost, in addition to the character action and interaction so a similar parkour demo came out, the following code also uses a plug-in for replacing the character action picture smoothie. Js tutorial to go
function setup () {
/ / the background
let bgSpr = new PIXI.extras.TilingSprite(PIXI.Loader.shared.resources['bg'].texture, app.renderer.width, app.renderer.height);
/ / outlook
let prospectSpr = new PIXI.extras.TilingSprite(PIXI.Loader.shared.resources['prospect'].texture, 1600.437);
/ / character
let role = new PIXI.Sprite(PIXI.Loader.shared.resources['role'].texture);
/ / the monster
let monster = new PIXI.Sprite(PIXI.Loader.shared.resources['monster'].texture);
let roleSmoothie = null; // Character animation
let monsterSmoothie = null; // Monster animation
let prospectSmoothie = null; // Foreground animation
let isBump = null; // Jump state
let roleSprGoIndex = 0; // walk action picture subscript
let roleSprRunIndex = 0; // Run action picture subscript
let roleSprJumpIndex = 0; // runout is used to subscript the image
let roleSprInverIndex = 0; // reverse action picture subscript
let prospectSpeed = 3; // Foreground speed
let isAction = true; // Action state
/ / center
prospectSpr.anchor.set(0.1);
role.anchor.set(0.5.1);
monster.anchor.set(0.5.1);
// Scale
role.scale.set(1.5.1.5);
monster.scale.set(3.3);
/ / position
role.position.set(300, app.renderer.height - 180);
monster.position.set(1500, app.renderer.height - 180);
prospectSpr.y = app.renderer.height;
// Add to the stage
app.stage.addChild(bgSpr, prospectSpr, role, monster);
/ / translation
function translate (spr, num) {
spr.tilePosition.x -= num;
spr.tilePosition.x %= PIXI.Loader.shared.resources['prospect'].texture.width;
};
// The monster moves
function monsterTranslate (spr, num, x) {
spr.position.x -= num;
spr.position.x < -x && (spr.position.x = 1600);
};
/ /.
function go () {
role.texture = PIXI.Loader.shared.resources[config.go[roleSprGoIndex]].texture;
roleSprGoIndex < 6? roleSprGoIndex++ : roleSprGoIndex = 0;
};
/ / run
function run () {
role.texture = PIXI.Loader.shared.resources[config.run[roleSprRunIndex]].texture;
if (roleSprRunIndex < 6) {
roleSprRunIndex++;
} else {
roleSprRunIndex = 0;
roleSmoothie.update = go.bind(this); }}/ / jump
function jump () {
role.texture = PIXI.Loader.shared.resources[config.jump[roleSprJumpIndex]].texture;
if (roleSprJumpIndex < 5) {
roleSprJumpIndex++;
role.position.y -= 30;
isAction = false;
} else {
roleSprJumpIndex = 0;
role.position.y = 570;
isAction = true;
roleSmoothie.update = go.bind(this); }}/ / the
function inverted (num) {
role.texture = PIXI.Loader.shared.resources[config.inverted[roleSprInverIndex]].texture;
if (roleSprInverIndex < num) {
roleSprInverIndex++;
isAction = false;
} else if (num === 6) {
isAction = true;
} else {
roleSprInverIndex = 0;
isAction = true;
roleSmoothie.update = go.bind(this); }}// The character moves
roleSmoothie = new Smoothie({
engine: PIXI,
renderer: app.renderer,
root: app.stage,
fps: 8.update: go.bind(this)}); roleSmoothie.start();// The monster moves
monsterSmoothie = new Smoothie({
engine: PIXI,
renderer: app.renderer,
root: app.stage,
update: monsterTranslate.bind(this, monster, 7.100)}); monsterSmoothie.start();// Foreground move
prospectSmoothie = new Smoothie({
engine: PIXI,
renderer: app.renderer,
root: app.stage,
update: translate.bind(this, prospectSpr, 3)}); prospectSmoothie.start();// Keyboard press event
$(document).keydown((e) = > {
if(! isAction)return;
e.keyCode === 38 && (roleSmoothie.update = jump.bind(this), prospectSmoothie.update = translate.bind(this, prospectSpr, 4));
e.keyCode === 39 && (roleSmoothie.update = run.bind(this), prospectSmoothie.update = translate.bind(this, prospectSpr, 6));
});
// The keyboard is lifted
$(document).keyup((e) = > {
prospectSmoothie.update = translate.bind(this, prospectSpr, 3);
});
app.ticker.add(() = > {
bgSpr.tilePosition.x -= 1;
bgSpr.tilePosition.x %= PIXI.Loader.shared.resources['bg'].texture.width;
bump(role, monster) && (roleSmoothie.update = inverted.bind(this.3));
});
/ / collision
function bump (spr1, spr2) {
spr1.anchor.set(0.5.1);
spr2.anchor.set(0.5.1);
if (spr1.x - spr2.x < spr2.width && spr1.x - spr2.x > -spr2.width) {
return spr1.y - spr2.y === 0? true : false;
} else {
return false; }}; }Copy the code
Project link: Demo
5, summary
Learning knowledge still needs to be done through practice, from practice we can see that there are many problems in the text tutorial, such as tile sprites will have accuracy problems over time, I did not know this problem will occur before the demo and it will not appear on the PC browser. Making a demo by learning a knowledge point can not only reinforce that knowledge point, but also extend it to other knowledge points, such as collision detection, Sprite texture switch, game loop, etc. Once you have a preliminary demo, you can add other features, such as health, scores, scene changes, overhead pillars and obstacles, and you have a simple little game.