I'm using a number of input controllers. One to control the camera and one to control buttons that have been placed on a scene.
Ive been trying to work out how to create my own custom controller but so far have been unsuccessful in finding any tutorials on how to do it.
Also i would like to deactivate the camera controller if the touch or gesture is bellow a certain height.
Many thanks in any help
Just create a class CamController implements InputProcessor (or extends InputAdapter).
Then override all the methods you need (i use touchDown here as an example) and do the following (Pseudocode!!! Do not copy and paste!!!):
protected boolean touchDown(int screenX, int screenY, int pointer, int button) {
boolean handled = false;
if (screenX <= maxX && screenX >= minX && screenY <= maxY && screenY >= minY) {
// The touch is inside the limits of the camera controller, the controller is activated
// Move camera to the touchpoint:
camera.position.set(screenX, screenY);
camra.update();
handled = true;
}
return handled;
}
Create the controller for the button, again the controller implements InputProcessor an override the methods.
Next in your ApplicationListener or in your Screens create() or show() method you create an InputMultiplexer:
InputMultiplexer m = new InputMultiplexer(new CamController(camera, limitX, limitY), new ButtonController);
And the you just need to set the InputMultiplexer as the active InputProcessor.
It's important to use CamController as the first one, because it then calls touchDown-method for this and only if the touchDown returns false it calls touchDown for the ButtonController.
Hope it helps.
Related
I am analizing a game code.
A method which name is act() is running despite it is not called.
Its like, there is a secret method somwere but i cant see it.
i follow source of method.i find so code.The some part of codes are as below.
I think parent class send method to child class when a new object execuded.
Is there a name of this approach.
This is LevelScreen class.It does not have act() method but act() method is working.I can see the changes when i change the parametres in act() method in Plane class.
class LevelScreen : BaseScreen(){
plane = Plane(100f, 500f, mainStage)}
This is Plane class which has act() method.
class Plane(x: Float, y: Float, s: Stage) : BaseActor(x, y, s){
override fun act(dt: Float) {
super.act(dt)
// simulate force of gravity
setAcceleration(800f)
accelerateAtAngle(270f)
applyPhysics(dt)
................
.............
}
This is parent class of Plane class
open class BaseActor(x: Float, y: Float, s: Stage) : Group(){
override fun act(dt: Float) {
super.act(dt)
if (!animationPaused)
elapsedTime += dt
}
}
This is a class which is in framework of libGDX
public class Group extends Actor implements Cullable{
public void act (float delta) {
super.act(delta);
Actor[] actors = children.begin();
for (int i = 0, n = children.size; i < n; i++)
actors[i].act(delta);
children.end();
}
}
Look at the main project file where the Stage is created. The main file will have a method called render and this is where the act method is called for the first time. All Actors are added to the Stage and then inside of the render method the act method is called on the Stage, which then calls the act method on all of the Actors that it contains.
This is the section you are looking for (taken from one of my projects):
#Override
public void render (){
Gdx.gl.glClearColor(0.6f, 0.64f, 0.7f, 1.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getRawDeltaTime()); // START OF ACT METHODS
stage.draw();
}
Is it possible to allow the user to touch an actor only one time.
I've tried using boolean but the problem is I write addListener in the class constructor and I want it to be here not in a separate method
I believe you can remove the listener like this, I have not tested it though and no time for it right now.
final Table t = new Table();
t.addListener(ClickListener listener = new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
//Do stuff
//...
//remove this listener
t.removeListener(this);
}
});
I'm new at Libgdx and one aspect that blocks me to continue with my Libgdx learning is the fact that a I don't know how to use the GestureListener. It's seems there's a user with the same doubt if you see in this link LibGdx: Utilizing a Gesture Listener, but it didn't help me much. So my question is: how do I use my own GestureListener class to process my player moviments? I wanna use the pan function to make it jump, but I don't know how to put my player object inside the method. If you see my gesture detector class:
public class GestureHandler implements GestureListener {
// Main Game class
private ClimbUp mainGame;
public GestureHandler(ClimbUp game) {
this.mainGame = game;
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean longPress(float x, float y) {
// TODO Auto-generated method stub
return false;
}
...
Then I followed what they told the user what to do: in the main class I passed the fallowing instruction:
Gdx.input.setInputProcessor(new GestureDetector(new GestureHandler(this)));
Now in my splash screen, I don't know how to use. How to make my GestureHandler object works for all project? I'll be very grateful with an answer!
So, you have some you class which need GestureListener "services" - you want to be informed when some gesture event happens and you want to have information of gesture properties.
Then, as you did, make your class implement GestureListener interface.
After that your IDE (Eclipse or Android Studio or something else) will complain that you didn't implemented all GestureListener methods, but it can also do that for you. If you (in eclipse) hover the error in the code IDE will offer you to create missing methods.
I would say you are at about that step. But now your methods have to do something useful. Like, if you want to do something when player taps the screen add your code inside that method. Do something there. Inside GestureListener methods you have some info available, as method parameters like x & y coordinates, button (left, middle, right) and something like that.
So, when you call that setInputProcessor with object created in you class that implemented G.L. interface libGDX will know to call your methods when some event occurs.
Every method IDE generated has that "todo" mark - that's where you have to put your code instead. The code that will handle that event, move your space ship, fire the bullet or what ever. You don't have to do something for every event, but only for those you are interested in. You can leave other empty, but your class must have them.
Here is some example:
// importing interface
import com.badlogic.gdx.input.GestureDetector.GestureListener;
// defining my class that implements that interface
public class TouchController implements GestureListener{
// constructor - just storing objects passed to it.
public TouchController(Playground pg, Army army, Hud hud){
super();
this.pg = pg;
this.army = army;
this.hud = hud;
initialZoom = pg.zoom;
}
// Adding some action to touchDown method - I'm just calling my hud object's method and passing coords I get
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
hud.pressedAt(x, pg.camera.viewportHeight-y); // opposite Y axis
// TODO Auto-generated method stub
return false;
}
// Similar thing. I unproject coords I get.
#Override
public boolean tap(float x, float y, int count, int button) {
if (!hud.buttonPressed){
Vector3 touchPos = new Vector3();
touchPos.set(x, y, 0);
pg.camera.unproject(touchPos);
army.add(touchPos.x, touchPos.y, SoldierSide.RED);
}else hud.released();
return false;
}
// Again similar stuff, but this pan methods is getting also delta value (difference from last reading x and y values) which can be useful
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
if (hud.aimDrag) hud.aimDragged((int)deltaX, (int)deltaY);
else if (hud.sliderDrag) hud.sliderDragged((int)deltaX, (int)deltaY);
else if (!hud.buttonPressed) pg.panned((int)deltaX, (int)deltaY);
return false;
}
...
I'm using repaint to trigger a SwingWorker. This worker automatically recreates an image to fit the width of the enclosing JPanel according to an autofit option in an application.
The issue is that is causing an Out of Memory Exception. This is because the images have a big resolution and the worker is being called continuously when the window is being drag-resized.
What I've tried to avoid this is only execute() when isDone() is true. However I feel there is a better way of doing this. Perhaps by using some sort of timer? What do you suggest?
It's a little left field, but basically what I do is use a javax.swing.Timer. The basic idea is to only perform an action when the timer fires.
private Timer timer;
.
.
.
timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Perform required action
// Start the swing worker ??
}
});
timer.setCoalesce(true);
timer.setRepeats(false);
.
.
.
public void setBounds(int x, int y, int width, int height) {
// Force the time to start/reset
timer.restart();
super.setBounds(x, y, width, height);
}
I'm a bit of a newb to as3 game development but I want to create a somewhat flexible base for a Connect Four game. I'd like to be able to skin the game board and game pieces. Here's what I'm thinking so far. If anyone has suggestions I'd really appreciate it:
GameController extends EventDispatcher
- Contains all game grid manipulation methods.
- Includes 2D array to keep track of GamePiece locations
- Dispatches events after validation when methods are invoked
GameClass extends Sprite:
- Holds visual elements of the board
- MouseEvent Listeners attached to visual elements, which invoke controller methods
- (Custom) ControllerEvent Listeners to update visual look when GameController dispatches
GamePiece Class extend Sprite:
- Holds piece's column/row location
- Holds currentPlayer index
- Loads PNG URL as skin
That's the rough outline. Any red flags or other suggestions are very much appreciated.
It sounds like the GridController is going to suffer from mixed responsibilities; in MVC architectures the Controller's responsibility is to shuffle data back and forth from the Model to the View. Personally I would consider having a GridModel which would hold the underlying multidimensional Array which represents the grid and methods for adding pieces, eg:
public class GridModel extends EventDispatcher {
private var _grid : Array;
public function GridModel(rows : uint, cols : uint) : void {
// Create the data structure which represents the Grid.
_grid = initialiseGrid(rows, cols);
}
public function addPiece(player : uint, col : uint) : void {
if (isValidMove(col)) {
// Update the datastructure, determine which row the piece ended
// up residing in.
const row : uint = // method omitted
// Notify the rest of the system that a move has been made.
dispatchEvent(new GridUpdateEvent(GridUpdateEvent.MOVE, player, col, row, _grid.concat());
}
else {
// Illegal Move, datastructure stays the same, notify the rest
// of the system.
dispatchEvent(new IllegalMoveEvent(IllegalMoveEvent.COLUMN_FULL, player, col, _grid.concat()));
}
}
}
The primary role of your Controller would now be to listen to the events dispatched by the model and then update the View (DisplayList) accordingly. Like-wise, your View should dispatch Events based on user interaction (eg: Player one has indicated that they wish to drop a piece into the 2nd column); the Controller can then call the relevant method on the Model.
The following snippet should give you some indication as to what the responsibilties of the Controller are; don't forget that you can (and should!) break your responsibilities down by making use of multiple Models, Views and, if required Controllers.
public class GameController {
private var _gridModel : GridModel;
private var _stateModel : GameStateModel;
private var _gridView : GridView;
public function GameController(gridModel : GridModel, gameStateModel : GameStateModel, gridView : GridView) {
_gridModel = gridModel;
_gameStateModel : gameStateModel;
_gridView = gridView;
addEventListeners();
}
private function addEventListeners() : void {
_gridModel.addEventListener(GridUpdateEvent.MOVE, onGridUpdateMoveEvent);
_gridView.addEventListener(ColumnSelectionEvent.SELECTED, onColumnSelectedEvent);
}
private function onColumnSelectedEvent(event : ColumnSelectionEvent) : void {
// Query the GameStateModel to find out whos turn it currently is.
const activePlayer : uint = _gameStateModel.activePlayer;
// Ask the GridModel to update.
_gridModel.addPiece(activePlayer, event.column);
}
private function onGridUpdateMoveEvent(event : GridUpdateEvent) : void {
// Update the view.
_gridView.insertPiece(event.player, event.row, event.col);
// Update the GameState to indicate it's the next player turns.
_gameSate.completeTurn();
}
}