gdx-studio

#libgdx#java#desktop

git clone https://git.pyrossh.dev/gdx-studio

An IDE for creating Games using libgdx and Java supported on all platforms Android, iOS, Desktop


src/scene2d/Scene.java
a9b2a64 1
package scene2d;
a9b2a64 2
import scene3d.Actor3d;
a9b2a64 3
import scene3d.Group3d;
a9b2a64 4
import scene3d.Stage3d;
a9b2a64 5
a9b2a64 6
import com.badlogic.gdx.ApplicationListener;
a9b2a64 7
import com.badlogic.gdx.Gdx;
a9b2a64 8
import com.badlogic.gdx.InputMultiplexer;
a9b2a64 9
import com.badlogic.gdx.graphics.Color;
a9b2a64 10
import com.badlogic.gdx.graphics.GL20;
a9b2a64 11
import com.badlogic.gdx.graphics.PerspectiveCamera;
a9b2a64 12
import com.badlogic.gdx.graphics.g2d.Batch;
a9b2a64 13
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
a9b2a64 14
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
a9b2a64 15
import com.badlogic.gdx.math.Intersector;
a9b2a64 16
import com.badlogic.gdx.math.MathUtils;
a9b2a64 17
import com.badlogic.gdx.math.Rectangle;
a9b2a64 18
import com.badlogic.gdx.math.Vector2;
a9b2a64 19
import com.badlogic.gdx.scenes.scene2d.Actor;
a9b2a64 20
import com.badlogic.gdx.scenes.scene2d.Group;
a9b2a64 21
import com.badlogic.gdx.scenes.scene2d.InputEvent;
a9b2a64 22
import com.badlogic.gdx.scenes.scene2d.Touchable;
a9b2a64 23
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
a9b2a64 24
import com.badlogic.gdx.scenes.scene2d.ui.Dialog;
a9b2a64 25
import com.badlogic.gdx.scenes.scene2d.ui.Image;
a9b2a64 26
import com.badlogic.gdx.scenes.scene2d.ui.Label;
a9b2a64 27
import com.badlogic.gdx.scenes.scene2d.ui.Table;
a9b2a64 28
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
a9b2a64 29
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
a9b2a64 30
import com.badlogic.gdx.utils.ArrayMap;
a9b2a64 31
import com.badlogic.gdx.utils.Json;
a9b2a64 32
import com.badlogic.gdx.utils.JsonReader;
a9b2a64 33
import com.badlogic.gdx.utils.JsonValue;
a9b2a64 34
import com.badlogic.gdx.utils.Scaling;
a9b2a64 35
import com.badlogic.gdx.utils.StringBuilder;
a9b2a64 36
import com.badlogic.gdx.utils.Timer;
a9b2a64 37
import com.badlogic.gdx.utils.Timer.Task;
a9b2a64 38
a9b2a64 39
abstract public class Scene extends Group {
a9b2a64 40
	/* The array map containing all the scenes data of the game*/
a9b2a64 41
	public static final ArrayMap<String, String> scenesMap = new ArrayMap<String, String>();
a9b2a64 42
	private String sceneName = "";
a9b2a64 43
	public String sceneBackground = "None";
a9b2a64 44
	public String sceneMusic = "None";
a9b2a64 45
	public String sceneTransition = "None";
a9b2a64 46
	public float sceneDuration = 0;
a9b2a64 47
	public InterpolationType sceneInterpolationType = InterpolationType.Linear;
a9b2a64 48
	
a9b2a64 49
	public static Color bgColor = new Color(1f,1f,1f,1f);
a9b2a64 50
	public static JsonValue configJson = null;
a9b2a64 51
	public static final JsonReader jsonReader = new JsonReader();
a9b2a64 52
	public static final Json json = new Json();
a9b2a64 53
	public static float splashDuration = 0f;
a9b2a64 54
	public static boolean pauseState = false;
a9b2a64 55
	/*Important:
a9b2a64 56
	 *  The Target Width  and Target Height refer to the nominal width and height of the game for the
a9b2a64 57
	 *  graphics which are created  for this width and height, this allows for the Stage to scale this
a9b2a64 58
	 *  graphics for all screen width and height. Therefore your game will work on all screen sizes 
a9b2a64 59
	 *  but maybe blurred or look awkward on some devices.
a9b2a64 60
	 *  ex:
a9b2a64 61
	 *  My Game targetWidth = 800 targetHeight = 480
a9b2a64 62
	 *  Then my game works perfectly for SCREEN_WIDTH = 800 SCREEN_HEIGHT = 480
a9b2a64 63
	 *  and on others screen sizes it is just zoomed/scaled but works fine thats all
a9b2a64 64
	 */
a9b2a64 65
	public static float targetWidth = 800;
a9b2a64 66
	public static float targetHeight  = 480;
a9b2a64 67
	public static boolean debug = false;
a9b2a64 68
	public final static Vector2 mouse = new Vector2();
a9b2a64 69
a9b2a64 70
	private static Scene currentScene = null;
a9b2a64 71
	private static int sceneIndex = 0;
a9b2a64 72
	
a9b2a64 73
	public static ClassLoader cl = null;
a9b2a64 74
	public static com.badlogic.gdx.scenes.scene2d.Stage stage2d;
a9b2a64 75
	public static Stage3d stage3d;
a9b2a64 76
	private static Label fpsLabel;
a9b2a64 77
	private static InputMultiplexer inputMux;
a9b2a64 78
a9b2a64 79
	public static int mousePointer = 0;
a9b2a64 80
	public static int mouseButton = 0;
a9b2a64 81
	public static boolean cullingEnabled = false;
a9b2a64 82
	public static boolean isDirty = false;
a9b2a64 83
	public static String basePackage = "source.";
a9b2a64 84
a9b2a64 85
	public Scene(){
a9b2a64 86
		setTouchable(Touchable.childrenOnly);
a9b2a64 87
		Camera.reset();
a9b2a64 88
		stage2d.clear();
a9b2a64 89
		stage3d.clear();
a9b2a64 90
		stage2d.addListener(touchInput);
a9b2a64 91
		setSize(targetWidth, targetHeight);
a9b2a64 92
		setBounds(0,0, targetWidth, targetHeight);
a9b2a64 93
		setColor(1f, 1f, 1f, 1f);
a9b2a64 94
		setVisible(true);
a9b2a64 95
		stage2d.getRoot().setPosition(0, 0);
a9b2a64 96
		stage2d.getRoot().setVisible(true);
a9b2a64 97
		stage3d.getRoot().setPosition(0, 0, 0);
a9b2a64 98
		stage3d.getRoot().setVisible(true);
a9b2a64 99
		sceneName = this.getClass().getName();
a9b2a64 100
		setName(sceneName);
a9b2a64 101
		Scene.log("Current Scene: "+sceneName);
a9b2a64 102
		currentScene = this;
a9b2a64 103
		load(sceneName);
a9b2a64 104
		cullingEnabled = true;
a9b2a64 105
	}
a9b2a64 106
a9b2a64 107
	@Override
a9b2a64 108
	public void act(float delta){
a9b2a64 109
		super.act(delta);
a9b2a64 110
		if (fpsLabel != null)
a9b2a64 111
			fpsLabel.setText("Fps: " + Gdx.graphics.getFramesPerSecond());
a9b2a64 112
	}
a9b2a64 113
a9b2a64 114
	public abstract void onClick(Actor actor);
a9b2a64 115
	public abstract void onTouchDown(Actor actor);
a9b2a64 116
	public abstract void onTouchUp();
a9b2a64 117
	public abstract void onDragged();
a9b2a64 118
	public abstract void onGesture(GestureType gestureType);
a9b2a64 119
	public abstract void onKeyTyped(char key);
a9b2a64 120
	public abstract void onKeyUp(int keycode);
a9b2a64 121
	public abstract void onKeyDown(int keycode);
a9b2a64 122
	/*
a9b2a64 123
	 * This will pause any music and stop any sound being played
a9b2a64 124
	 * and will fire the Pause event
a9b2a64 125
	 */
a9b2a64 126
	public abstract void onPause();
a9b2a64 127
	/*
a9b2a64 128
	 * This will resume any music currently being played
a9b2a64 129
	 * and will fire the Resume event
a9b2a64 130
	 */
a9b2a64 131
	public abstract void onResume();
a9b2a64 132
	public abstract void onDispose();
a9b2a64 133
a9b2a64 134
	public void load(String sceneName){
a9b2a64 135
		log("Load "+sceneName);
a9b2a64 136
		if(!sceneName.contains(basePackage) && !sceneName.contains("gdxstudio"))
a9b2a64 137
			sceneName = basePackage+sceneName;
a9b2a64 138
		String[] lines = scenesMap.get(sceneName).split("\n");
a9b2a64 139
		for(String line: lines){
a9b2a64 140
			if(line.trim().isEmpty())
a9b2a64 141
				continue;
a9b2a64 142
			json.fromJson(null, line);
a9b2a64 143
			//log(line);
a9b2a64 144
		}
a9b2a64 145
		if(!sceneBackground.equals("None"))
a9b2a64 146
			setBackground(sceneBackground);
a9b2a64 147
		if(!sceneMusic.equals("None"))
a9b2a64 148
			Asset.musicPlay(sceneMusic);
a9b2a64 149
		if(!sceneTransition.equals("None"))
a9b2a64 150
			Effect.createEffect(Scene.getRoot(), EffectType.valueOf(sceneTransition), 1f,
a9b2a64 151
					sceneDuration, sceneInterpolationType);
a9b2a64 152
	}
a9b2a64 153
a9b2a64 154
	protected void save(){
a9b2a64 155
		save(sceneName);
a9b2a64 156
	}
a9b2a64 157
a9b2a64 158
	public void save(String sceneName){
a9b2a64 159
		if(!isDirty)
a9b2a64 160
			return;
a9b2a64 161
		if(sceneName == null || sceneName.isEmpty())
a9b2a64 162
			return;
a9b2a64 163
		Scene.log("Save "+sceneName);
a9b2a64 164
		if(!sceneName.contains(basePackage) && !sceneName.contains("gdxstudio"))
a9b2a64 165
			sceneName = basePackage+sceneName;
a9b2a64 166
		StringBuilder sb = new StringBuilder();
a9b2a64 167
		for(Actor actor: getChildren()){
a9b2a64 168
			sb.append(json.toJson(actor));
a9b2a64 169
			sb.append("\n");
a9b2a64 170
		}
a9b2a64 171
		sb.append(json.toJson(getRoot().findActor(this.sceneName)));//??Warning
a9b2a64 172
		scenesMap.put(sceneName, sb.toString());
a9b2a64 173
		Gdx.files.local(Asset.basePath+"scene").writeString(json.toJson(scenesMap, ArrayMap.class, 
a9b2a64 174
				String.class), false);
a9b2a64 175
		sb = null;
a9b2a64 176
		isDirty = false;
a9b2a64 177
	}
a9b2a64 178
	
a9b2a64 179
	/**
a9b2a64 180
	 * Set the current scene to be displayed
a9b2a64 181
	 * @param className The scene's Class Name
a9b2a64 182
	 **/
a9b2a64 183
	public static void setScene(String className){
a9b2a64 184
		if(!className.contains(basePackage) && !className.contains("gdxstudio"))
a9b2a64 185
			className = basePackage+className;
a9b2a64 186
		if(!scenesMap.containsKey(className)){
a9b2a64 187
			log(className+": Scene Does not Exist");
a9b2a64 188
			return;
a9b2a64 189
		}
a9b2a64 190
		/*
a9b2a64 191
		 *  Every time the scene Changes disable panning/following/listening as it can cause the 
a9b2a64 192
		 *  camera to move around aimlessly, thus abrupting the scene and clear 
a9b2a64 193
		 *  all the listeners/huds that were registered in the previous scene
a9b2a64 194
		 */
a9b2a64 195
		sceneIndex = Scene.scenesMap.keys().toArray().indexOf(className, false);
a9b2a64 196
		if(currentScene != null)
a9b2a64 197
			currentScene.onDispose();
a9b2a64 198
		try {
a9b2a64 199
			if(cl != null)
a9b2a64 200
				cl.loadClass(className).newInstance();
a9b2a64 201
			else
a9b2a64 202
				Class.forName(className).newInstance();
a9b2a64 203
		} catch (InstantiationException e) {
a9b2a64 204
			log("Scene cannot be created , Check if scene class constructor is empty");
a9b2a64 205
			e.printStackTrace();
a9b2a64 206
		} catch (IllegalAccessException e) {
a9b2a64 207
			log("Scene cannot be created , Check if scene class can be found");
a9b2a64 208
			e.printStackTrace();
a9b2a64 209
		} catch (ClassNotFoundException e) {
a9b2a64 210
			log("Scene cannot be created , Check if scene class can be found");
a9b2a64 211
			e.printStackTrace();
a9b2a64 212
		}
a9b2a64 213
		//if (fpsLabel != null && configJson.getBoolean("showFPS")){
a9b2a64 214
		//	fpsLabel.setPosition(targetWidth - 80, targetHeight - 20);
a9b2a64 215
		//	Camera.addHud(fpsLabel);
a9b2a64 216
		//}
a9b2a64 217
	}
a9b2a64 218
a9b2a64 219
	/**
a9b2a64 220
	 * Set the current scene to be displayed with an amount of delay
a9b2a64 221
	 * @param className The registered scene's name
a9b2a64 222
	 **/
a9b2a64 223
	public static void setSceneWithDelay(final String className, float delay){
a9b2a64 224
		Timer.schedule(new Task(){
a9b2a64 225
			@Override
a9b2a64 226
			public void run() {
a9b2a64 227
				setScene(className);
a9b2a64 228
			}
a9b2a64 229
		}, delay);
a9b2a64 230
	}
a9b2a64 231
a9b2a64 232
	/**
a9b2a64 233
	 * Returns the current scene being Displayed on stage
a9b2a64 234
	 **/
a9b2a64 235
	public static Scene getCurrentScene(){
a9b2a64 236
		return currentScene;
a9b2a64 237
	}
a9b2a64 238
a9b2a64 239
	/**
a9b2a64 240
	 * Changes to the next scene in the scnesList
a9b2a64 241
	 **/
a9b2a64 242
	public static void nextScene(){
a9b2a64 243
		if(sceneIndex <= scenesMap.size)
a9b2a64 244
			sceneIndex++;
a9b2a64 245
		setScene(scenesMap.getKeyAt(sceneIndex));
a9b2a64 246
	}
a9b2a64 247
a9b2a64 248
	/**
a9b2a64 249
	 * Changes to the previous scene in the scnesList
a9b2a64 250
	 **/
a9b2a64 251
	public static void prevScene(){
a9b2a64 252
		if(sceneIndex >= 0)
a9b2a64 253
			sceneIndex--;
a9b2a64 254
		setScene(scenesMap.getKeyAt(sceneIndex));
a9b2a64 255
	}
a9b2a64 256
a9b2a64 257
	/**
a9b2a64 258
	 * Changes to the next scene in the scnesList
a9b2a64 259
	 **/
a9b2a64 260
	public static void nextSceneWithDelay(float delay){
a9b2a64 261
		if(sceneIndex <= scenesMap.size)
a9b2a64 262
			sceneIndex++;
a9b2a64 263
		setSceneWithDelay(Scene.scenesMap.getKeyAt(sceneIndex), delay);
a9b2a64 264
	}
a9b2a64 265
a9b2a64 266
	/**
a9b2a64 267
	 * Changes to the previous scene in the scnesList
a9b2a64 268
	 **/
a9b2a64 269
	public static void prevSceneWithDelay(float delay){
a9b2a64 270
		if(sceneIndex >= 0)
a9b2a64 271
			sceneIndex--;
a9b2a64 272
		setSceneWithDelay(scenesMap.getKeyAt(sceneIndex), delay);
a9b2a64 273
	}
a9b2a64 274
a9b2a64 275
	private static Image imgbg = null;
a9b2a64 276
	public void setBackground(String texName) {
a9b2a64 277
		if(imgbg != null)
a9b2a64 278
			removeBackground();
a9b2a64 279
		if(Asset.tex(texName) != null){
a9b2a64 280
			imgbg = new Image(new TextureRegionDrawable(Asset.tex(texName)), Scaling.stretch);
a9b2a64 281
			imgbg.setFillParent(true);
a9b2a64 282
			stage2d.addActor(imgbg);
a9b2a64 283
			imgbg.toBack();
a9b2a64 284
		}
a9b2a64 285
	}
a9b2a64 286
a9b2a64 287
	public void removeBackground() {
a9b2a64 288
		getRoot().removeActor(imgbg);
a9b2a64 289
	}
a9b2a64 290
	
a9b2a64 291
	public static Group getRoot(){
a9b2a64 292
		return stage2d.getRoot();
a9b2a64 293
	}
a9b2a64 294
	
a9b2a64 295
	public void addActor(Actor actor, float x, float y){
a9b2a64 296
		if(actor != null){
a9b2a64 297
			actor.setPosition(x, y);
a9b2a64 298
			addActor(actor);
a9b2a64 299
		}
a9b2a64 300
	}
a9b2a64 301
a9b2a64 302
	public void addActorWithDelay(final Actor actor, float delay){
a9b2a64 303
		Timer.schedule(new Task(){
a9b2a64 304
			@Override
a9b2a64 305
			public void run() {
a9b2a64 306
				addActor(actor);
a9b2a64 307
			}
a9b2a64 308
		}, delay);
a9b2a64 309
	}
a9b2a64 310
a9b2a64 311
	public boolean removeActor(String actorName){
a9b2a64 312
		return removeActor(findActor(actorName));
a9b2a64 313
	}
a9b2a64 314
a9b2a64 315
	public void removeActorWithDelay(Actor actor, float delay){
a9b2a64 316
		addAction(Actions.sequence(Actions.delay(delay), Actions.removeActor(actor)));
a9b2a64 317
	}
a9b2a64 318
a9b2a64 319
	public Actor hit(float x, float y){
a9b2a64 320
		return hit(x, y, true);
a9b2a64 321
	}
a9b2a64 322
a9b2a64 323
a9b2a64 324
	/* Dragging Camera Related */
a9b2a64 325
	static boolean gestureStarted = false;
a9b2a64 326
	static Actor validActor = null;
a9b2a64 327
	private final ClickListener touchInput = new ClickListener(){
a9b2a64 328
		@Override
a9b2a64 329
		public void clicked(InputEvent event, float x, float y){
a9b2a64 330
			super.clicked(event, x, y);
a9b2a64 331
			mouse.set(x, y);
a9b2a64 332
			validActor = hit(x,y);
a9b2a64 333
			if(validActor != null && validActor.getName() != null)
a9b2a64 334
				Scene.getCurrentScene().onClick(validActor);
a9b2a64 335
		}
a9b2a64 336
a9b2a64 337
		@Override
a9b2a64 338
		public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
a9b2a64 339
			mouse.set(x, y);
a9b2a64 340
			mousePointer = pointer;
a9b2a64 341
			mouseButton = button;
a9b2a64 342
			touchInitialX = x;
a9b2a64 343
			touchInitialY = y;
a9b2a64 344
			gestureStarted = true;
a9b2a64 345
			validActor = hit(x,y);
a9b2a64 346
			if(validActor != null && validActor.getName() != null)
a9b2a64 347
				Scene.getCurrentScene().onTouchDown(validActor);
a9b2a64 348
			return super.touchDown(event, x, y, pointer, button);
a9b2a64 349
		}
a9b2a64 350
a9b2a64 351
a9b2a64 352
		@Override
a9b2a64 353
		public void touchDragged(InputEvent event, float x, float y, int pointer){
a9b2a64 354
			super.touchDragged(event, x, y, pointer);
a9b2a64 355
			mouse.set(x, y);
a9b2a64 356
			mousePointer = pointer;
a9b2a64 357
			Scene.getCurrentScene().onDragged();
a9b2a64 358
			if(gestureStarted == true){
a9b2a64 359
				touchCurrentX = x;
a9b2a64 360
				touchCurrentY = y;
a9b2a64 361
				if(getGestureDirection() != GestureType.None){
a9b2a64 362
					gestureStarted = false;
a9b2a64 363
					Scene.getCurrentScene().onGesture(getGestureDirection());
a9b2a64 364
				}
a9b2a64 365
			}
a9b2a64 366
			if(Camera.useDrag) 
a9b2a64 367
				Camera.dragCam((int)x, (int)-y);
a9b2a64 368
		}
a9b2a64 369
a9b2a64 370
		@Override
a9b2a64 371
		public void touchUp(InputEvent event, float x, float y, int pointer, int button){
a9b2a64 372
			super.touchUp(event, x, y, pointer, button);
a9b2a64 373
			mouse.set(x, y);
a9b2a64 374
			mousePointer = pointer;
a9b2a64 375
			mouseButton = button;
a9b2a64 376
			// reset Gesture
a9b2a64 377
			difX = 0.0f;
a9b2a64 378
			difY = 0.0f;
a9b2a64 379
			touchInitialX = 0.0f;
a9b2a64 380
			touchInitialY = 0.0f;
a9b2a64 381
			touchCurrentX = 0.0f;
a9b2a64 382
			touchCurrentY = 0.0f;
a9b2a64 383
			touchDifX = 0.0f;
a9b2a64 384
			touchDifY = 0.0f;
a9b2a64 385
			prevDifX = 0.0f;
a9b2a64 386
			prevDifY = 0.0f;
a9b2a64 387
			// reset Gesture
a9b2a64 388
			Scene.getCurrentScene().onTouchUp();
a9b2a64 389
			Camera.resetDrag();
a9b2a64 390
			gestureStarted = false;
a9b2a64 391
		}
a9b2a64 392
a9b2a64 393
		@Override
a9b2a64 394
		public boolean keyTyped(InputEvent event, char key) {
a9b2a64 395
			Scene.getCurrentScene().onKeyTyped(key);
a9b2a64 396
			return super.keyUp(event, key);
a9b2a64 397
		}
a9b2a64 398
a9b2a64 399
		@Override
a9b2a64 400
		public boolean keyUp(InputEvent event, int keycode) {
a9b2a64 401
			Scene.getCurrentScene().onKeyUp(keycode);
a9b2a64 402
			return super.keyUp(event, keycode);
a9b2a64 403
		}
a9b2a64 404
		@Override
a9b2a64 405
		public boolean keyDown(InputEvent event, int keycode) {
a9b2a64 406
			Scene.getCurrentScene().onKeyDown(keycode);
a9b2a64 407
			return super.keyDown(event, keycode);
a9b2a64 408
		}
a9b2a64 409
	};
a9b2a64 410
a9b2a64 411
	/* 
a9b2a64 412
	 * Gesture related
a9b2a64 413
	 */
a9b2a64 414
	public static float touchDragIntervalRange = 200f; // 200px drag for a gesture event
a9b2a64 415
	public static float touchInitialX = 0.0f, touchInitialY = 0.0f;
a9b2a64 416
	public static float touchCurrentX = 0.0f, touchCurrentY = 0.0f;
a9b2a64 417
	public static float difX;
a9b2a64 418
	public static float difY;
a9b2a64 419
	public static float prevDifX;
a9b2a64 420
	public static float prevDifY;
a9b2a64 421
	public static float touchDifX;
a9b2a64 422
	public static float touchDifY;
a9b2a64 423
a9b2a64 424
	public boolean isTouchDragInterval() {
a9b2a64 425
		difX = java.lang.Math.abs(touchInitialX - touchCurrentX);
a9b2a64 426
		difY = java.lang.Math.abs(touchInitialY - touchCurrentY);
a9b2a64 427
		if (difX > touchDragIntervalRange || difY > touchDragIntervalRange) 
a9b2a64 428
			return true;
a9b2a64 429
		else 
a9b2a64 430
			return false;
a9b2a64 431
	}
a9b2a64 432
a9b2a64 433
	public static GestureType getGestureDirection() {
a9b2a64 434
		prevDifX = difX;
a9b2a64 435
		prevDifY = difY;
a9b2a64 436
		difX = java.lang.Math.abs(touchInitialX - touchCurrentX);
a9b2a64 437
		difY = java.lang.Math.abs(touchInitialY - touchCurrentY);
a9b2a64 438
		/**
a9b2a64 439
		 * Get minimal changes on drag
a9b2a64 440
		 * <p> checkMomentumChanges
a9b2a64 441
		 * EXAMPLE<br>
a9b2a64 442
		 * User drags finger to left, suddenly dragging to right without removing
a9b2a64 443
		 * his finger from the screen
a9b2a64 444
		 * */
a9b2a64 445
		if (prevDifX > difX || prevDifY > difY) {
a9b2a64 446
			touchInitialX = touchCurrentX;
a9b2a64 447
			touchInitialY = touchCurrentY;
a9b2a64 448
			//
a9b2a64 449
			difX = 0.0f;
a9b2a64 450
			difY = 0.0f;
a9b2a64 451
			prevDifX = 0.0f;
a9b2a64 452
			prevDifY = 0.0f;
a9b2a64 453
a9b2a64 454
			/**
a9b2a64 455
			 * Set touch differences, optional, if you need amount of change from
a9b2a64 456
			 * initial touch to drag, USE THIS: on touchDrag, pan or similar mthods
a9b2a64 457
			 * */
a9b2a64 458
			touchDifX = java.lang.Math.abs(touchInitialX - touchCurrentX);
a9b2a64 459
			touchDifY = java.lang.Math.abs(touchInitialY - touchCurrentY);
a9b2a64 460
		}
a9b2a64 461
		if (touchInitialY < touchCurrentY && difY > difX) {
a9b2a64 462
			return GestureType.Up;
a9b2a64 463
		} else if (touchInitialY > touchCurrentY && difY > difX) {
a9b2a64 464
			return GestureType.Down;
a9b2a64 465
		} else if (touchInitialX < touchCurrentX && difY < difX) {
a9b2a64 466
			return GestureType.Right;
a9b2a64 467
		} else if (touchInitialX > touchCurrentX && difY < difX) {
a9b2a64 468
			return GestureType.Left;
a9b2a64 469
		} else {
a9b2a64 470
			return GestureType.None;
a9b2a64 471
		}
a9b2a64 472
	}
a9b2a64 473
a9b2a64 474
	/* 
a9b2a64 475
	 * Dialog Methods
a9b2a64 476
	 */
a9b2a64 477
	public void showToast(String message, float duration){
a9b2a64 478
		Table table = new Table(Asset.skin);
a9b2a64 479
		table.add("   "+message+"   ");
a9b2a64 480
		table.setBackground(Asset.skin.getDrawable("dialogDim"));
a9b2a64 481
		table.pack();
a9b2a64 482
		table.setPosition(Scene.targetWidth/2 - table.getWidth(), Scene.targetHeight/2 - table.getHeight());
a9b2a64 483
		addActor(table);
a9b2a64 484
		table.addAction(Actions.sequence(Actions.delay(duration), Actions.removeActor(table)));
a9b2a64 485
	}
a9b2a64 486
a9b2a64 487
	public void showMessageDialog(String title, String message){
a9b2a64 488
		Dialog dialog = new Dialog(title, Asset.skin);
a9b2a64 489
		dialog.getContentTable().add(message);
a9b2a64 490
		dialog.button("OK", "OK");
a9b2a64 491
		dialog.pack();
a9b2a64 492
		dialog.show(getStage());
a9b2a64 493
	}
a9b2a64 494
a9b2a64 495
	public boolean showConfirmDialog(String title, String message){
a9b2a64 496
		Dialog dialog = new Dialog(title, Asset.skin);
a9b2a64 497
		dialog.button("Yes", "Yes");
a9b2a64 498
		dialog.button("No", "No");
a9b2a64 499
		dialog.pack();
a9b2a64 500
		dialog.show(getStage());
a9b2a64 501
		//if(dialog.result().equals("Yes")) FIXME update Gdx
a9b2a64 502
		//	return true;
a9b2a64 503
		return false;
a9b2a64 504
	}
a9b2a64 505
	
a9b2a64 506
	public void outline(Actor actor){
a9b2a64 507
		selectionBox.setPosition(actor.getX(), actor.getY());
a9b2a64 508
		selectionBox.setSize(actor.getWidth(), actor.getHeight());
a9b2a64 509
		stage2d.addActor(selectionBox);
a9b2a64 510
	}
a9b2a64 511
a9b2a64 512
/***********************************************************************************************************
a9b2a64 513
* 					3d Related Functions												   	       		   *
a9b2a64 514
************************************************************************************************************/	
a9b2a64 515
a9b2a64 516
	public static void addActor3d(Actor3d actor3d){
a9b2a64 517
		stage3d.addActor3d(actor3d);
a9b2a64 518
	}
a9b2a64 519
a9b2a64 520
	public static void removeActor3d(Actor3d actor3d){
a9b2a64 521
		stage3d.getRoot().removeActor3d(actor3d);
a9b2a64 522
	}
a9b2a64 523
	
a9b2a64 524
	public static void removeActor3d(String actor3dName){
a9b2a64 525
		getRoot3d().removeActor3d(stage3d.getRoot().findActor(actor3dName));
a9b2a64 526
	}
a9b2a64 527
	
a9b2a64 528
	public static Group3d getRoot3d(){
a9b2a64 529
		return stage3d.getRoot();
a9b2a64 530
	}
a9b2a64 531
a9b2a64 532
	public static void getChildren3d(){
a9b2a64 533
		stage3d.getActors3d();
a9b2a64 534
	}
a9b2a64 535
a9b2a64 536
	public static void resetCamera3d(){
a9b2a64 537
		stage3d.getCamera().position.set(10f, 10f, 10f);
a9b2a64 538
		stage3d.getCamera().lookAt(0,0,0);
a9b2a64 539
		stage3d.getCamera().near = 0.1f;
a9b2a64 540
		stage3d.getCamera().far = 300f;
a9b2a64 541
	}
a9b2a64 542
a9b2a64 543
	public static PerspectiveCamera getCamera3d(){
a9b2a64 544
		return stage3d.getCamera();
a9b2a64 545
	}
a9b2a64 546
	
a9b2a64 547
a9b2a64 548
	public static void log(String log) {
a9b2a64 549
		if(Scene.configJson.getBoolean("loggingEnabled"))
a9b2a64 550
			Gdx.app.log("Stage ", log);
a9b2a64 551
	}
a9b2a64 552
a9b2a64 553
	
a9b2a64 554
/***********************************************************************************************************
a9b2a64 555
* 					Utilities Related Functions												   	       		   *
a9b2a64 556
************************************************************************************************************/
a9b2a64 557
	/*
a9b2a64 558
	 * The the angle in degrees of the inclination of a line
a9b2a64 559
	 * @param cx, cy The center point x, y
a9b2a64 560
	 * @param tx, ty The target point x, y
a9b2a64 561
	 */
a9b2a64 562
	public static float getAngle(float cx, float cy, float tx, float ty) {
a9b2a64 563
		float angle = (float) Math.toDegrees(MathUtils.atan2(tx - cx, ty - cy));
a9b2a64 564
		//if(angle < 0){
a9b2a64 565
		//    angle += 360;
a9b2a64 566
		//}
a9b2a64 567
		return angle;
a9b2a64 568
	}
a9b2a64 569
a9b2a64 570
	private static Vector2 distVector = new Vector2();
a9b2a64 571
	public static final float getDistance(Actor a, Actor b){
a9b2a64 572
		distVector.set(a.getX(), a.getY());
a9b2a64 573
		return distVector.dst(b.getX(), b.getY());
a9b2a64 574
	}
a9b2a64 575
a9b2a64 576
	public static final float getDistance(float x1, float y1, float x2, float y2){
a9b2a64 577
		distVector.set(x1, y1);
a9b2a64 578
		return distVector.dst(x2, y2);
a9b2a64 579
	}
a9b2a64 580
a9b2a64 581
	/*
a9b2a64 582
	 * Capitalizes the First Letter of a String
a9b2a64 583
	 */
a9b2a64 584
	public static String capitalize(String text){
a9b2a64 585
		if(text != null && text != "")
a9b2a64 586
			return (text.substring(0, 1)).toUpperCase() + text.substring(1);
a9b2a64 587
		else
a9b2a64 588
			return "";
a9b2a64 589
	}
a9b2a64 590
a9b2a64 591
	/*
a9b2a64 592
	 * UnCapitalizes the First Letter of a String
a9b2a64 593
	 */
a9b2a64 594
	public static String uncapitalize(String text){
a9b2a64 595
		return text.substring(0, 1).toLowerCase()+text.substring(1);
a9b2a64 596
	}
a9b2a64 597
a9b2a64 598
	public static Rectangle getBounds(Actor actor) {
a9b2a64 599
		float posX = actor.getX();
a9b2a64 600
		float posY = actor.getY();
a9b2a64 601
		float width = actor.getWidth();
a9b2a64 602
		float height = actor.getHeight();
a9b2a64 603
		return new Rectangle(posX, posY, width, height);
a9b2a64 604
	}
a9b2a64 605
a9b2a64 606
	public static boolean collides(Actor actor, float x, float y) {
a9b2a64 607
		Rectangle rectA1 = getBounds(actor);
a9b2a64 608
		Rectangle rectA2 = new Rectangle(x, y, 5, 5);
a9b2a64 609
		// Check if rectangles collides
a9b2a64 610
		if (Intersector.overlaps(rectA1, rectA2)) {
a9b2a64 611
			return true;
a9b2a64 612
		} else {
a9b2a64 613
			return false;
a9b2a64 614
		}
a9b2a64 615
	}
a9b2a64 616
a9b2a64 617
	public static boolean collides(Actor actor1, Actor actor2) {
a9b2a64 618
		Rectangle rectA1 = getBounds(actor1);
a9b2a64 619
		Rectangle rectA2 = getBounds(actor2);
a9b2a64 620
		// Check if rectangles collides
a9b2a64 621
		if (Intersector.overlaps(rectA1, rectA2)) {
a9b2a64 622
			return true;
a9b2a64 623
		} else {
a9b2a64 624
			return false;
a9b2a64 625
		}
a9b2a64 626
	}
a9b2a64 627
	
a9b2a64 628
a9b2a64 629
	/**
a9b2a64 630
	 * Get screen time from start in format of HH:MM:SS. It is calculated from
a9b2a64 631
	 * "secondsTime" parameter.
a9b2a64 632
	 * */
a9b2a64 633
	public static String toScreenTime(float secondstime) {
a9b2a64 634
		int seconds = (int)(secondstime % 60);
a9b2a64 635
		int minutes = (int)((secondstime / 60) % 60);
a9b2a64 636
		int hours =  (int)((secondstime / 3600) % 24);
a9b2a64 637
		return new String(addZero(hours) + ":" + addZero(minutes) + ":" + addZero(seconds));
a9b2a64 638
	}
a9b2a64 639
	
a9b2a64 640
	private static String addZero(int value){
a9b2a64 641
		String str = "";
a9b2a64 642
		if(value < 10)
a9b2a64 643
			 str = "0" + value;
a9b2a64 644
		else
a9b2a64 645
			str = "" + value;
a9b2a64 646
		return str;
a9b2a64 647
	}
a9b2a64 648
	
a9b2a64 649
	/*
a9b2a64 650
	 * TEA Encryption and Decryption
a9b2a64 651
	 */
a9b2a64 652
	public static String encryptKey = "Default";
a9b2a64 653
	private static final int encryptDelta = 0x9E3779B9;
a9b2a64 654
	private static final int MX(int sum, int y, int z, int p, int e, int[] k) {
a9b2a64 655
		return (z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z);
a9b2a64 656
	}
a9b2a64 657
	
a9b2a64 658
	public static final byte[] encrypt(String data) {
a9b2a64 659
		return encrypt(data.getBytes(), encryptKey.getBytes());
a9b2a64 660
	}
a9b2a64 661
a9b2a64 662
	public static final byte[] decrypt(String data) {
a9b2a64 663
		return decrypt(data.getBytes(), encryptKey.getBytes());
a9b2a64 664
	}
a9b2a64 665
a9b2a64 666
	public static final byte[] encrypt(String data, String key) {
a9b2a64 667
		return encrypt(data.getBytes(), key.getBytes());
a9b2a64 668
	}
a9b2a64 669
a9b2a64 670
	public static final byte[] decrypt(String data, String key) {
a9b2a64 671
		return decrypt(data.getBytes(), key.getBytes());
a9b2a64 672
	}
a9b2a64 673
a9b2a64 674
	private static final byte[] encrypt(byte[] data, byte[] key) {
a9b2a64 675
		if (data.length == 0) 
a9b2a64 676
			return data;
a9b2a64 677
		return toByteArray(encrypt(toIntArray(data, true), toIntArray(key, false)), false);
a9b2a64 678
	}
a9b2a64 679
a9b2a64 680
a9b2a64 681
	private static final byte[] decrypt(byte[] data, byte[] key) {
a9b2a64 682
		if (data.length == 0)
a9b2a64 683
			return data;
a9b2a64 684
		return toByteArray(decrypt(toIntArray(data, false), toIntArray(key, false)), true);
a9b2a64 685
	}
a9b2a64 686
a9b2a64 687
	private static final int[] encrypt(int[] v, int[] k) {
a9b2a64 688
		int n = v.length - 1;
a9b2a64 689
		if (n < 1) {
a9b2a64 690
			return v;
a9b2a64 691
		}
a9b2a64 692
		if (k.length < 4) {
a9b2a64 693
			int[] key = new int[4];
a9b2a64 694
a9b2a64 695
			System.arraycopy(k, 0, key, 0, k.length);
a9b2a64 696
			k = key;
a9b2a64 697
		}
a9b2a64 698
		int z = v[n], y = v[0], sum = 0, e;
a9b2a64 699
		int p, q = 6 + 52 / (n + 1);
a9b2a64 700
a9b2a64 701
		while (q-- > 0) {
a9b2a64 702
			sum = sum + encryptDelta;
a9b2a64 703
			e = sum >>> 2 & 3;
a9b2a64 704
	for (p = 0; p < n; p++) {
a9b2a64 705
		y = v[p + 1];
a9b2a64 706
		z = v[p] += MX(sum, y, z, p, e, k);
a9b2a64 707
	}
a9b2a64 708
	y = v[0];
a9b2a64 709
	z = v[n] += MX(sum, y, z, p, e, k);
a9b2a64 710
		}
a9b2a64 711
		return v;
a9b2a64 712
	}
a9b2a64 713
a9b2a64 714
	private static final int[] decrypt(int[] v, int[] k) {
a9b2a64 715
		int n = v.length - 1;
a9b2a64 716
a9b2a64 717
		if (n < 1) {
a9b2a64 718
			return v;
a9b2a64 719
		}
a9b2a64 720
		if (k.length < 4) {
a9b2a64 721
			int[] key = new int[4];
a9b2a64 722
a9b2a64 723
			System.arraycopy(k, 0, key, 0, k.length);
a9b2a64 724
			k = key;
a9b2a64 725
		}
a9b2a64 726
		int z = v[n], y = v[0], sum, e;
a9b2a64 727
		int p, q = 6 + 52 / (n + 1);
a9b2a64 728
a9b2a64 729
		sum = q * encryptDelta;
a9b2a64 730
		while (sum != 0) {
a9b2a64 731
			e = sum >>> 2 & 3;
a9b2a64 732
		for (p = n; p > 0; p--) {
a9b2a64 733
			z = v[p - 1];
a9b2a64 734
			y = v[p] -= MX(sum, y, z, p, e, k);
a9b2a64 735
		}
a9b2a64 736
		z = v[n];
a9b2a64 737
		y = v[0] -= MX(sum, y, z, p, e, k);
a9b2a64 738
		sum = sum - encryptDelta;
a9b2a64 739
		}
a9b2a64 740
		return v;
a9b2a64 741
	}
a9b2a64 742
a9b2a64 743
a9b2a64 744
	private static final int[] toIntArray(byte[] data, boolean includeLength) {
a9b2a64 745
		int n = (((data.length & 3) == 0)
a9b2a64 746
				? (data.length >>> 2)
a9b2a64 747
						: ((data.length >>> 2) + 1));
a9b2a64 748
		int[] result;
a9b2a64 749
a9b2a64 750
		if (includeLength) {
a9b2a64 751
			result = new int[n + 1];
a9b2a64 752
			result[n] = data.length;
a9b2a64 753
		}
a9b2a64 754
		else {
a9b2a64 755
			result = new int[n];
a9b2a64 756
		}
a9b2a64 757
		n = data.length;
a9b2a64 758
		for (int i = 0; i < n; i++) {
a9b2a64 759
			result[i >>> 2] |= (0x000000ff & data[i]) << ((i & 3) << 3);
a9b2a64 760
		}
a9b2a64 761
		return result;
a9b2a64 762
	}
a9b2a64 763
a9b2a64 764
a9b2a64 765
	private static final byte[] toByteArray(int[] data, boolean includeLength) {
a9b2a64 766
		int n = data.length << 2;
a9b2a64 767
a9b2a64 768
		if (includeLength) {
a9b2a64 769
			int m = data[data.length - 1];
a9b2a64 770
a9b2a64 771
			if (m > n) {
a9b2a64 772
				return null;
a9b2a64 773
			}
a9b2a64 774
			else {
a9b2a64 775
				n = m;
a9b2a64 776
			}
a9b2a64 777
		}
a9b2a64 778
		byte[] result = new byte[n];
a9b2a64 779
a9b2a64 780
		for (int i = 0; i < n; i++) {
a9b2a64 781
			result[i] = (byte) ((data[i >>> 2] >>> ((i & 3) << 3)) & 0xff);
a9b2a64 782
		}
a9b2a64 783
		return result;
a9b2a64 784
	}
a9b2a64 785
	
a9b2a64 786
	private static ShapeRenderer shapeRenderer;
a9b2a64 787
	private final static Actor selectionBox = new Actor(){
a9b2a64 788
		@Override
a9b2a64 789
		public void draw(Batch batch, float alpha){
a9b2a64 790
			batch.end();
a9b2a64 791
			shapeRenderer.begin(ShapeType.Line);
a9b2a64 792
			shapeRenderer.setColor(Color.GREEN);
a9b2a64 793
			shapeRenderer.rect(getX(), getY(), 
a9b2a64 794
						getWidth(),getHeight());
a9b2a64 795
			shapeRenderer.end();
a9b2a64 796
			batch.begin();
a9b2a64 797
		}
a9b2a64 798
	};
a9b2a64 799
	
a9b2a64 800
	static void setupFps(){
a9b2a64 801
		fpsLabel = new Label("", Asset.skin);
a9b2a64 802
		fpsLabel.setName("Fps");
a9b2a64 803
	}
a9b2a64 804
	public static float stateTime = 0;
a9b2a64 805
	public static float gameUptime = 0;
a9b2a64 806
	private static float startTime = System.nanoTime();
a9b2a64 807
	/*
a9b2a64 808
	 *  The main application listener for the game
a9b2a64 809
	 */
a9b2a64 810
	public static ApplicationListener app = new ApplicationListener() {
a9b2a64 811
		public int dots = 40;
a9b2a64 812
		public int xlines;
a9b2a64 813
		public int ylines;
a9b2a64 814
		@Override
a9b2a64 815
		public final void create() {
a9b2a64 816
			log("Create");
a9b2a64 817
			Config.setup();
a9b2a64 818
			Serializer.setup();
a9b2a64 819
			stage2d = new com.badlogic.gdx.scenes.scene2d.Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),
a9b2a64 820
					Scene.configJson.getBoolean("keepAspectRatio"));
a9b2a64 821
			stage2d.getRoot().setName("Root");
a9b2a64 822
			stage2d.getRoot().setTouchable(Touchable.childrenOnly);
a9b2a64 823
			stage2d.setCamera(new Camera());
a9b2a64 824
			inputMux = new InputMultiplexer();
a9b2a64 825
			inputMux.addProcessor(stage2d);
a9b2a64 826
			stage3d = new Stage3d();
a9b2a64 827
			//camController = new CameraInputController(stage3d.getCamera());
a9b2a64 828
			//inputMux.addProcessor(stage3d);
a9b2a64 829
			//inputMux.addProcessor(camController);
a9b2a64 830
			shapeRenderer = new ShapeRenderer();
a9b2a64 831
			selectionBox.setTouchable(Touchable.disabled);
a9b2a64 832
			selectionBox.setName("Shape");
a9b2a64 833
			JsonValue sv = Scene.jsonReader.parse(Gdx.files.internal(Asset.basePath+"scene"));
a9b2a64 834
			for(JsonValue jv: sv.iterator())
a9b2a64 835
				scenesMap.put(jv.name, jv.asString());
a9b2a64 836
			setScene(scenesMap.firstKey());
a9b2a64 837
			Gdx.input.setCatchBackKey(true);
a9b2a64 838
			Gdx.input.setCatchMenuKey(true);
a9b2a64 839
			Gdx.input.setInputProcessor(inputMux);
a9b2a64 840
			xlines = (int)Gdx.graphics.getWidth()/dots;
a9b2a64 841
	 		ylines = (int)Gdx.graphics.getHeight()/dots;
a9b2a64 842
		}
a9b2a64 843
		/*
a9b2a64 844
		 * This is the main rendering call that updates the time, updates the stage,
a9b2a64 845
		 * loads assets asynchronously, updates the camera and FPS text.
a9b2a64 846
		 */
a9b2a64 847
		@Override
a9b2a64 848
		public final void render(){
a9b2a64 849
			Gdx.gl.glClearColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a);
a9b2a64 850
			Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT |GL20.GL_DEPTH_BUFFER_BIT);
a9b2a64 851
			if (System.nanoTime() - startTime >= 1000000000) {
a9b2a64 852
				gameUptime +=1 ;
a9b2a64 853
				startTime = System.nanoTime();
a9b2a64 854
			}
a9b2a64 855
			stateTime += Gdx.graphics.getDeltaTime();
a9b2a64 856
			Asset.load();
a9b2a64 857
			stage3d.act();
a9b2a64 858
			stage3d.draw();
a9b2a64 859
		    //camController.update();
a9b2a64 860
			Scene.stage2d.act();//Gdx.graphics.getDeltaTime();
a9b2a64 861
			Scene.stage2d.draw();
a9b2a64 862
			if(debug){
a9b2a64 863
				shapeRenderer.begin(ShapeType.Point);
a9b2a64 864
				shapeRenderer.setColor(Color.BLACK);
a9b2a64 865
				for(int i = 0; i<=xlines; i++)
a9b2a64 866
					for(int j = 0; j<=ylines; j++)
a9b2a64 867
						shapeRenderer.point(2+i*dots, j*dots, 0);
a9b2a64 868
				shapeRenderer.end();
a9b2a64 869
			}
a9b2a64 870
	 	}
a9b2a64 871
		@Override
a9b2a64 872
		public final void resize(int width, int height) {
a9b2a64 873
			log("Resize");
a9b2a64 874
			stage2d.setViewport(targetWidth, targetHeight, configJson.getBoolean("keepAspectRatio"));
a9b2a64 875
			stage3d.setViewport(targetWidth, targetHeight, configJson.getBoolean("keepAspectRatio"));
a9b2a64 876
		}
a9b2a64 877
		@Override
a9b2a64 878
		public final void pause() {
a9b2a64 879
			log("Pause");
a9b2a64 880
			Asset.musicPause();
a9b2a64 881
			Asset.soundStop();
a9b2a64 882
			Scene.pauseState = true;
a9b2a64 883
			Scene.getCurrentScene().onPause();
a9b2a64 884
		}
a9b2a64 885
		@Override
a9b2a64 886
		public final void resume() {
a9b2a64 887
			log("Resume");
a9b2a64 888
			Asset.musicResume();
a9b2a64 889
			Scene.pauseState = false;
a9b2a64 890
			Scene.getCurrentScene().onResume();
a9b2a64 891
		}
a9b2a64 892
		@Override
a9b2a64 893
		public final void dispose() {
a9b2a64 894
			log("Dispose");
a9b2a64 895
			Scene.getCurrentScene().onDispose();
a9b2a64 896
			Scene.stage2d.dispose();
a9b2a64 897
			Asset.unloadAll();
a9b2a64 898
			Gdx.app.exit();
a9b2a64 899
		}
a9b2a64 900
	};
a9b2a64 901
	
a9b2a64 902
	public static final void exit(){
a9b2a64 903
		log("Disposing and Exiting");
a9b2a64 904
		getCurrentScene().onDispose();
a9b2a64 905
		stage2d.dispose();
a9b2a64 906
		stage3d.dispose();
a9b2a64 907
		Asset.unloadAll();
a9b2a64 908
		Gdx.app.exit();
a9b2a64 909
	}
a9b2a64 910
a9b2a64 911
	
a9b2a64 912
	public enum GestureType {
a9b2a64 913
		None, Up, Down, Left, Right
a9b2a64 914
	}
a9b2a64 915
	
a9b2a64 916
	public enum OnEventType {
a9b2a64 917
		DoEffect,
a9b2a64 918
		SetScene
a9b2a64 919
	}
a9b2a64 920
	
a9b2a64 921
}