Top-down game camera movement - actionscript-3

I'm developing a top-down view game, and I've got a problem with the camera.
Currently camera simply follows the player entity - it seems fine to me, but people want another camera.
I'm using Starling, and StarlingPunk, but it shouldn't make much difference, its more theoretical question.
Camera works like this:
public function centerOnEntity(target:SPEntity):void
{
var newCameraX:Number = (target.x + target.width / 2) - SP.width / 2;
var newCameraY:Number = (target.y + target.height / 2) - SP.height / 2;
SP.camera.setPosition(newCameraX, newCameraY);
}
And basically, every frame, camera is centered on the user.
Following image will demonstrate the problem:
As you can see, I've got rectangular levels, and if level is small, or user is near to the level bounds a background image is displayed.
So, what kind of camera do I need?
I need a camera, that will show maximum level space, and minimum background image.
How can I achieve that?
Help would be appreciated!

Related

flash actionscript 3.0 hide part of an image

I am working on a flash sound mixer application with multiple sound channels, and I am having trouble with the lights beside the volume knob.
Is there a way to hide just a part of an image?
On the image below, image-2 is on top of image-1 to create some kind of volume level indicator effect, and how much of image-2 is shown depends on the value of the volume.
image-url: http://s30.postimg.org/r3ow1g5bl/volume_lights_level.png
I've tried by just reducing the height of image-2, but it looks awful and distorted.
Is there something in flash that works closely the same as CSS's behavior.
example: I'll just make image-2 a background of a shape, and when I reduce the shape's height, the image-background does not get distorted or changes it's height as well.
By searching for solutions, I have come across the mask property, but I don't quite understand how it works, and most of the examples shown are images placed inside circles.
Is the mask property applicable in this situation?
I'm quite new to flash so I don't know a lot of things yet.
You can indeed use a mask.
How to programmatically create your mask
Put an occurrence of your image named myImage on the stage, and put over this occurrence a mask named myMask with the same dimensions. You can apply myMask mask to myImage using it's mask property like below:
Main Timeline
myImage.mask = myMask;
function mouseMoveHandler(e:MouseEvent):void {
myMask.height = myImage.y - e.stageY;
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
You have just to adapt this code to your animation, in the function where you click your button.
I got it working now, many THANKS #VC.One. heres how I did it.
Imported img-2 to stage, converted it into symbol(type:Movie Clip), assigned instance name: img2_mc.
I created a new layer for the mask, drawn a rectangle using rectangle tool, converted it also to symbol(type:Movie Clip), assigned instance name: mask_mc.
Then applied the mask to img2_mc.
/* the code */
img2_mc.mask = mask_mc;
function onEnterFrame(event:Event):void{
var volumeKnob_y = volSliderKnobOn.y + 12; // adjust it to the center of the knob
mask_mc.height = volumeKnob_y;
}

Understand LibGDX Coordinate system and drawing sprites

So I am super stoked to start using LibGDX for my first android title for OUYA and PC, but I am running into some snags with LibGDX. (All of my questions can be answered by looking at source, but I am really trying to understand the design choices as well).
To start with, the coordinate system. I created a project using the Project Setup jar, and it creates an OrthographicCamera like so
camera = new OrthographicCamera(1, h/w);
From my reading, I understand that LibGdx uses bottom left corner for 0,0 and yUp. Fine.
I see that it is pretty easy to change to y down if I want to, but I am not understanding the next bit of code that was created.
For the default sprite that gets created the position is set like so.
logoSprite.setOrigin(logoSprite.getWidth()/2, logoSprite.getHeight()/2);
logoSprite.setPosition(-logoSprite.getWidth()/2, -logoSprite.getHeight()/2);
When I run this basic program, I see the logo image I have added is centered on the screen. What I am trying to understand is why the values are negative in set position, and why is it using the sprite width and height instead of the graphics w and h of the view port? If I change to the screen width and height, then the image is drawn in some odd position in the lower right hand side of the screen.
My next question is sprite.setSize vs sprite.setScale. Why is the difference between the two? (They appear to do the same thing, except setScale leaves getWidth and getHeight unchanged).
Since my game will be using a 2D camera heavily for panning, zooming and rotation, I am trying to understand as much as I can about the libgdx framework before I start writing any code.
As a side note, I have a game development and math background and I have made several 2D and 3D games using XNA. I am finding LibGdx a bit frustrating as it does not abstract away OpenGL as much as I was expecting it to, and so far the 2D drawing I have been experimenting with seems to be more confusing than it should be!
I also wanted to note that I am planning to use spine for my animations. Should that change my choice to use y-up or y-down?
If you want to draw a sprite in center of screen, do this in your create method
logosprite.setposition(scrw/2-logosprite.getwidth()/2,scrh/2-logosprite.getheight/2);
here scrw is your viewport's width,
and scrh is your viewport's height,
this way your sprite will be in center of screen
sprite.setsize is used for setting size of the sprite and sprite.setscale is used when we scale a large/small texture so that its quality remains good in all devices(hdpi.mdpi,xhdpi,ldpi)..
no need to worry if you are using spine it works smoothly in libgdx..
You can use just this code if possible
logoSprite.setPosition(Gdx.graphics.getWidth()/2 - image.getWidth()/2,
Gdx.graphics.getHeight()/2 - image.getHeight()/2);
To center the sprite into the middle of the screen Where "image" is the Texture you have loaded/declared initially.
As for why it is coming in a odd position is due to the fact that you are using a camera.
Which changes the view a lot just go through the documentations of libgdx about camera here
In my case, I needed to set position of camera and then call update() method.
Then never forget camera's (0,0) is its center. Everything is being placed that way. My camera code:
private void cameralariUpdateEt() {
cameraGame.position.set(cameraGame.viewportWidth * 0.5f,
cameraGame.viewportHeight * 0.5f, 0);
cameraGame.update();
cameraScore.position.set(cameraScore.viewportWidth * 0.5f,
cameraScore.viewportHeight * 0.5f, 0);
cameraScore.update();
}
Call this method from inside render();
Step 1: Set the sprite origin to the position you would like it to rotate around.
// camera center point is (c.x, c.y)
logoSprite.setOrigin(c.x, c.y);
Step 2: make sure to set your sprite center to origin
logoSprite.setOriginCenter();
Step 3: Rotate your sprite
logoSprite.setRotation(Angle);
Step 4: Set the sprite position, [subtract half the sprites width and height to center the sprite]
logoSprite.setPosition(c.x - logoSprite.getWidth() / 2, c.y - logoSprite.getHeight() / 2)

scaling object to match field of view

I am overlaying some clickable hotspots on top of a proprietary panorama viewer application in flash (as3), and I need to make sure that the hotspots scale according to the changing field of view as the user zooms in / zooms out, but I'm not sure what formula to use.
I set a maximum and minimum field of view of 90 and 25, respectively. I've been given some suggestions of how to calculate the scale of the icons:
from the maker of the panorama software:
Scale => 1/tan(FoV)
This doesn't seem to work for me. And:
scalar += (ZOOM_SCALE_UPPER - ZOOM_SCALE_LOWER) * ( ZOOM_LIMIT_OUT - tempFOV )/( ZOOM_LIMIT_OUT-ZOOM_LIMIT_IN) ;
hotspot.scaleX = hotspot.scaleY = scalar;
Gets me close, but at some point the hotspot stops scaling even though the panorama continues to scale. I thought I could just do something like:
diffFOV = previousFOV - currentFOV.
hotspot.scale = currentScale*(1-diffFov)
But that's not quite right either. Everything gets way too big or too small.
Any ideas?
You may be over thinking it.
//assume we change the scale
var NEW_SCALE:Number = currentScale*(1-(previousFOV-currentFOV));
//1. change the scale of the parent containing both the view and the hotspots
viewSprite.scale = NEW_SCALE;
//this way the hotspot and the panorama will scale together
//2. if they are not in the same parent... then set them both to the same view
hotspot.scale = panorama.scale;
Only thing you may have to do after is reposition if they are not registered on their center point.

How to make a fluid/liquid Air application using Flash?

What I need is take advantage of the all area of the screen, independent of user's screen proportions.
By default, Air apps scales proportionately from the inside out. This would be great if we hadn't so different screens sizes and proportions in Android.
Angry Birds is a good example of what I call of fluid layout, it always scales/zooms the three layers(front, game and background layer) accordinly.
My app is mostly a inteface based game, the user must see some info and click on some buttons. I think I could base my scale primarily in the user screen's width, and use a scroll if needed. The problem is how do that.
Fluid / liquid / responsive layouts would likely imply a layout manager of some kind.
This functionality is built in to Flex.
Per Flash, and more specifically to what you've noted per requirements it sounds like some basic scaling and positioning is what you desire.
Layers
As you've noted, different layers will have different requirements per scaling:
background
game play
interface / controls
Background and game play might be a single layer; however, you may want different constraints on the foreground user controls for readability and interaction.
Setting up the stage
If you want to control scaling, you should set:
import flash.display.StageAlign;
import flash.display.StageScaleMode;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
This also assists with orientation change of mobile devices swapping between portrait and landscape.
Browsers can be resized; so, you need to listen for resize events:
stage.addEventListener(Event.RESIZE, resizeHandler);
stage.dispatchEvent(new Event(Event.RESIZE));
function resizeHandler(event:Event=null):void
{
/* scale code ... */
}
Positioning
Top and left positioning are always easy, because top-left is 0x0 coordinate. Right and bottom require subtracting a DisplayObject width from stage.
Right align example:
mc.x = stage.stageWidth - mc.width;
Bottom align example:
mc.y = stage.stageHeight - mc.height;
Keeping something in the center of the stage:
mc.x = (stage.stageWidth * 0.5) - (mc.width * 0.5);
mc.y = (stage.stageHeight * 0.5) - (mc.height * 0.5);
Scaling
You need to determine what your constraint is to avoid blank / empty regions on the stage.
This can be implemented using a ratio variable:
var ratio:Number = 1.0;
Proportional scaling:
ratio = stage.stageWidth / gameMovieClip.width;
gameMovieClip.scaleX = ratio;
gameMovieClip.scaleY = ratio;
Stretch display object to fit stage:
gameMovieClip.scaleX = stage.stageWidth / gameMovieClip.width;
gameMovieClip.scaleY = stage.stageHeight / gameMovieClip.height;
Best fit algorithms require fitting the minimum constraint of your display object within a bounds. There are libraries that can assist with this, such as Greensock auto fit area.
Virtual Cameras
Virtual cameras have been popular in Flash. The concept is that you design your view then pan and zoom a camera to show a specific region.
O'Reilly ActionScript for Non-Coders
Example 1
Example 2
Example 3
Virtual camera FLA example:
http://bryanheisey.com/blog/wp-content/uploads/2009/02/vcam_as3.fla
Virtual camera example:
http://www.fluidanims.com/FAelite/phpBB3/viewtopic.php?f=43&t=3369
http://www.neoseeker.com/forums/87/t647746-cam-virtual-cam-for-flash-mx-lower-level-intermediate/
http://www.flashkit.com/movies/Components/Flash_V--_redesig-10378/index.php
Google "Flash virtual camera" or "Flash v-cam" for examples.

AS3 - can't scrub through FLV using netstream.seek() after FLV finishes loading

I'm trying to play an FLV using the Netstream class - standard stuff, really using nothing more complex than things you can find in the help files. I've created a control panel with a bar you can use to click and drag and scrub through the video.
Exporting to Flash Player 9, it's working fine and I can scrub through the video, but only while the FLV is still loading. As soon as it hits 100% the scrubbing (using Netstream.seek()) becomes incredibly unresponsive, almost to the point of crashing the player.
I've killed all ENTER_FRAMES, removed all unnecessary listeners and nullified everything I can think of but something massively resource-intensive seems to be kicking in as soon as the load finishes.
Has anyone ever seen this? I've never come across this and can't find anything similar across assorted forums.
Code below but I don't think the mouse-move drag actions are the problem! Fine in the Flash CS4 IDE, broken in the browser.
Thanks for any help you might be able to provide,
Gareth
// Drag
private function dragVideo(e:MouseEvent):void {
// Match the x position of the dragger to the x position of the mouse
videoControls.progressBar.dragger.x = videoControls.progressBar.barInner.mouseX;
// If this results in the dragger moving outside the dragging area, constrain it
if (videoControls.progressBar.dragger.x < videoProgressRectangle.left) {
videoControls.progressBar.dragger.x = videoProgressRectangle.left;
} else if (videoControls.progressBar.dragger.x > videoProgressRectangle.right) {
videoControls.progressBar.dragger.x = videoProgressRectangle.right;
}
// As the dragger moves, work out its position as a percentage of the total distance it CAN move
// That distance is the width of the black inner bar but you must also accomodate the centred registration point of the dragger
// So knock off half the dragger's width from it's current position (which gives the left edge of the inner bar)
// Then knock off the dragger's width minus the 2px overhang of the white progress bar border, from the total draggable distance
videoSeekPercentageMouse = (videoControls.progressBar.dragger.x - (videoControls.progressBar.dragger.width / 2)) / (videoControls.progressBar.barInner.width - (videoControls.progressBar.dragger.width - 2));
// Now use that percentage to seek the video to the equivalent percentage of its total time
if (videoSeekPercentageMouse <= 0) {
videoNetStream.seek(0);
} else if (videoSeekPercentageMouse >= 1) {
// Because video metaData says the length is xyz while the real length is xyz + 0.015,
// seek to slightly before the end
videoNetStream.seek(videoDuration - 0.016);
} else {
videoNetStream.seek(videoDuration * videoSeekPercentageMouse);
}
// Show the video's current progress
videoControls.progressBar.barProgress.scaleX = videoSeekPercentageMouse;
// After the mouse moves update the display
e.updateAfterEvent();
}
Got it!
You should try this..
Pause the streaming "before" seeking..
Seek()
And then resume the streaming!