I have found a tutorial on parallax scrolling in spritekit using objective-C though I have been trying to port it to swift without much success, very little in fact.
Parallax Scrolling
Does anyone have any other tutorials or methods of doing parallax scrolling in swift.
This is a SUPER simple way of starting a parallax background. WITH SKACTIONS! I am hoping it helps you understand the basics before moving to a harder but more effective way of coding this.
So I'll start with the code that get a background moving and then you try duplicating the code for the foreground or objects you want to put in your scene.
//declare ground picture. If Your putting this image over the top of another image (use a png file).
var groundImage = SKTexture(imageNamed: "background.jpg")
//make your SKActions that will move the image across the screen. this one goes from right to left.
var moveBackground = SKAction.moveByX(-groundImage.size().width, y: 0, duration: NSTimeInterval(0.01 * groundImage.size().width))
//This resets the image to begin again on the right side.
var resetBackGround = SKAction.moveByX(groundImage.size().width, y: 0, duration: 0.0)
//this moves the image run forever and put the action in the correct sequence.
var moveBackgoundForever = SKAction.repeatActionForever(SKAction.sequence([moveBackground, resetBackGround]))
//then run a for loop to make the images line up end to end.
for var i:CGFloat = 0; i<2 + self.frame.size.width / (groundImage.size().width); ++i {
var sprite = SKSpriteNode(texture: groundImage)
sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2)
sprite.runAction(moveBackgoundForever)
self.addChild(sprite)
}
}
//once this is done repeat for a forground or other items but them run at a different speed.
/*make sure your pictures line up visually end to end. Just duplicating this code will NOT work as you will see but it is a starting point. hint. if your using items like simple obstructions then using actions to spawns a function that creates that obstruction maybe a good way to go too. If there are more then two separate parallax objects then using an array for those objects would help performance. There are many ways to handle this so my point is simple: If you can't port it from ObjectiveC then rethink it in Swift. Good luck!
Related
I create a macOS single window application and add a Sprite Particle System file with template Stars. and the visual effect just like this:
And I want to add it to my viewController, as the guide of this answer, I got the result like this, and it was not which I desired:
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
let particlesNode = SCNNode()
let particleSystem = SCNParticleSystem(named: "Welcome", inDirectory: "")
particlesNode.addParticleSystem(particleSystem!)
scene.rootNode.addChildNode(particlesNode)
skView.backgroundColor = .black
skView.scene = scene
}
So, I'm wondering what's wrong and what should I do?
Here is the demo repo: Link Here
The particle system itself is the standard "star" SceneKit particle system available in Xcode, with no changes.
Well I made a little progress. If I swivel the camera around 180 degrees, I can see the stars receding, so we can tell that the particle system is running ok. In the default orientation, though, all I saw was blinking lights. So I think the particles are being generated with a Z position of 0, the same as the camera's.
If I move the system's node away from the camera
particlesNode.position = SCNVector3(0, 0, -20)
I still just see blinking lights. But if I click on the SCNView, the animation works correctly. I see stars coming at me.
I don't understand why I have to click the view to get it to work right. I tried isPlaying = true but that made no difference.
I'm trying to make a small project using Three.js & the physics plugin physijs; just a little dice roller. My approach is to use setGravity to move the dice around, modelling gravity to move the dice around. The issue I'm running into is that once the dice come to a rest, they no longer respond to gravity. Has anyone run into this before?
Whats happening:
Ammo.js, on which Physijs is based, puts resting or very slow moving objects in a sleep state to save performance. So when you change the worlds gravity the sleeping objects dont care, because Physijs doesnt tell them gravity has changed.
You have the ability to modify the sleeping thresholds, set activation states or just quickly activate the rigid bodys before changing gravity.
Please note this code applys to native Ammo.js, I am not sure how to
do this when using physijs but you get the idea.
Solution 1: Loop over your Bodys and activate them, then change gravity:
// dice is an array with your rigid bodys
for ( var i = 0; i < dice.length; i ++ ) {
// hey wake up
dice[ i ].activate();
}
physicsWorld.setGravity( new Ammo.btVector3( 0, -9.81, 0 ) );
Solution 2: Thou shall get no sleep, do this after creating your dice:
var DISABLE_DEACTIVATION = 4;
for ( var i = 0; i < dice.length; i ++ )
// no sleep for you... ever
dice[ i ].setActivationState( DISABLE_DEACTIVATION );
}
I need to add a picture to a spacetree to serve as a background to a spacetree.
I have tried several ways but succeeded at none, mainly for the following 2 reasons:
- positioning on the canvas (coordinates 0,0 do not seem to be the correct positioning. it is in the minus!)
- each time the spacetree redraws, it clear the canvas.
Any help will be sincerely appreciated.
guys, what I did is straight forward: if you use the example from the infovis spacetree,
please add the following right after :
st.compute();
//optional: make a translation of the tree
st.geom.translate(new $jit.Complex(-200, 0), "current");
//what I added
//where myimage is an image I load in the DOM normally.
var ctx = st.canvas.getCtx();
var imageObj = document.getElementById("myimage");
ctx.drawImage(imageObj, -700, -500);
I have some images/sprites/buttons (i tried them all :)) scrolling/moving on the stage. The user has to tap them to remove them.
The problem is that the touchevent does not match the position of the image.
The faster the touchable sprites move, the further the distance between the touch and the actual image. i.e.:
a image is moving across the screen with 20px/frame:
Touching the image triggers nothing, touching 20 before it triggers a touch on the image.
when image is not moving, this doesn't happen. It seems that the image is already moved internally, but not yet drawn to the screen, but thats just a wild guess. The example below uses a button, but the same goes for an image. I"ll provide a short example of the code, but i guess its pretty straightforward what i'm trying to do.
private var _image:Button;
protected function init():void {
//create pickup image
_image = new Button(assets.getTexture("button"));
_image.scaleWhenDown = 1;
_image.addEventListener(Event.TRIGGERED, onClick_image);
addChild(_image);
//listen to touch event (not used, but example for touch on image instead of button
//touchable = true;
//addEventListener(TouchEvent.TOUCH, onTouch_image);
}
private function onEnter_frame(e:Event):void {
_image.x -= 20;
}
I've written a home-brew view_port class for a 2D strategy game. The panning (with arrow keys) and zooming (with mouse wheel) work fine, but I'd like the view to also home towards wherever the cursor is placed, as in Google Maps or Supreme Commander
I'll spare you the specifics of how the zoom is implemented and even what language I'm using: this is all irrelevant. What's important is the zoom function, which modifies the rectangle structure (x,y,w,h) that represents the view. So far the code looks like this:
void zoom(float delta, float mouse_x, float mouse_y)
{
zoom += delta;
view.w = window.w/zoom;
view.h = window.h/zoom;
// view.x = ???
// view.y = ???
}
Before somebody suggests it, the following will not work:
view.x = mouse_x - view.w/2;
view.y = mouse_y - view.h/2;
This picture illustrates why, as I attempt to zoom towards the smiley face:
As you can see when the object underneath the mouse is placed in the centre of the screen it stops being under the mouse, so we stop zooming towards it!
If you've got a head for maths (you'll need one) any help on this would be most appreciated!
I managed to figure out the solution, thanks to a lot of head-scratching a lot of little picture: I'll post the algorithm here in case anybody else needs it.
Vect2f mouse_true(mouse_position.x/zoom + view.x, mouse_position.y/zoom + view.y);
Vect2f mouse_relative(window_size.x/mouse_pos.x, window_size.y/mouse_pos.y);
view.x = mouse_true.x - view.w/mouse_relative.x;
view.y = mouse_true.y - view.h/mouse_relative.y;
This ensures that objects placed under the mouse stay under the mouse. You can check out the code over on github, and I also made a showcase demo for youtube.
In my concept there is a camera and a screen.
The camera is the moving part. The screen is the scalable part.
I made an example script including a live demo.
The problem is reduced to only one dimension in order to keep it simple.
https://www.khanacademy.org/cs/cam-positioning/4772921545326592
var a = (mouse.x + camera.x) / zoom;
// now increase the zoom e.g.: like that:
zoom = zoom + 1;
var newPosition = a * zoom - mouse.x;
camera.setX(newPosition);
screen.setWidth(originalWidth * zoom);
For a 2D example you can simply add the same code for the height and y positions.