I have about 25 levels in my game,and each one will get loaded automatically when previous one has completed.
When I click play button to start the game,game screen is getting loaded with obstacles from JSON. But there is a jerk happening initially when game is just start playing.
This is my class where I am doing JSON parsing for the levels :
public class ObstacleFactory {
public static Array<Obstacle> obstacles1 = new Array<Obstacle>();
public static Array<String> names = new Array<String>();
public ObstacleFactory() {
}
public static void loadJsonLevels(String fileName) {
JsonValue jsonValue = new JsonReader().parse(Gdx.files.internal(fileName));
JsonValue nameValue = jsonValue.get("obstacles");
for (JsonValue value : nameValue.iterator()) {
System.out.println(nameValue);
if (value.getString("name").equals("rock")) {
obstacles1.add(new Obstacle());
obstacles1.get(obstacles1.size - 1).setName(value.getString("name"));
obstacles1.get(obstacles1.size - 1).setDistance(value.getFloat("distance"));
obstacles1.get(obstacles1.size - 1).setPos(value.getString("position"));
obstacles1.get(obstacles1.size - 1).setSpeed(value.getFloat("speed"));
if (value.getString("position").equals("middle"))
obstacles1.get(obstacles1.size - 1).setPosition(value.getFloat("distance"), Constants.BIG_ROCK_Y);
obstacles1.get(obstacles1.size - 1).setSize(Constants.ROCK_WIDTH, Constants.ROCK_HEIGHT);
names.add(value.getString("name"));
}
if (value.getString("name").equals("gorilla")) {
obstacles1.add(new Obstacle());
obstacles1.get(obstacles1.size - 1).setName(value.getString("name"));
obstacles1.get(obstacles1.size - 1).setDistance(value.getFloat("distance"));
obstacles1.get(obstacles1.size - 1).setPos(value.getString("position"));
obstacles1.get(obstacles1.size - 1).setSpeed(value.getFloat("speed"));
if (value.getString("position").equals("middle"))
obstacles1.get(obstacles1.size - 1).setPosition(value.getFloat("distance"), Constants.GORILLA_Y);
obstacles1.get(obstacles1.size - 1).setSize(Constants.GORILLA_WIDTH, Constants.GORILLA_HEIGHT);
names.add(value.getString("name"));
}
// ------------other obstacles
// -------------other obstacles
names.add(value.getString("name"));
}
}
}
}
This loadJsonLevels() I am calling in GameScreen class(where I am writing all the gamelogic,and texture loading for the obstacles from JSON and other game object.)constructor like this:
ObstacleFactory.loadJsonLevels("levels/level1.json");
ObstacleFactory.loadJsonLevels("levels/level2.json");
Every time I starts,or restarts the game,this jerk is there and should be removed because it is annoying.
What are the possible reasons for this issue?
I posted code related to json parsing and level loading because this jerk happening when I call this loadJsonLevel().If I comment it,jerk is not there.
I hope I will be able to get some useful suggestion to overcome this issue.
Thanks in advance.
You're probably starting to show the screen before the data has been fully loaded.
It's a pretty expensive operation (or can be, especially on low resource devices) to open, read, and write files or networks.
You don't want to do that in your main display thread, and you don't want to do it while the screen is being drawn.
Good reason for that cut scene or something else to keep the user waiting for a few seconds.
Related
I have been working in AS3 to stream 1080P video on YouTube and video gets start uploading and almost 4-5 minutes of the video has been uploaded successfully and afterwards YouTube shows that stream has been ended, but FFMPEG will never hits on "Exit" or any other method even after waiting for next 10 minutes.
Below is the method I am using.
public var _nativeProcessStartupInfo:NativeProcessStartupInfo;
public var _processArgs:Vector.<String>;
public var _process:NativeProcess;
protected function StartVideo_clickHandler(event:MouseEvent):void
{
_nativeProcessStartupInfo.executable = File.applicationStorageDirectory.resolvePath("ffmpeg.exe Path");
_processArgs.push('-re');
_processArgs.push('-i');
_processArgs.push(VideoPath);
_processArgs.push('-vcodec');
_processArgs.push('copy');
_processArgs.push('-acodec');
_processArgs.push('copy');
_processArgs.push('-maxrate');
_processArgs.push('4500k');
_processArgs.push('-bufsize');
_processArgs.push('9000k');
_processArgs.push('-pix_fmt');
_processArgs.push('yuv422p');
_processArgs.push('-preset');
_processArgs.push('fast');
_processArgs.push('-ac');
_processArgs.push('2');
_processArgs.push('-r');
_processArgs.push('30');
_processArgs.push('-g');
_processArgs.push('60');
_processArgs.push('-ar');
_processArgs.push('44100');
_processArgs.push('-f');
_processArgs.push('flv');
_processArgs.push(streamurl+'/'+streamname);
_nativeProcessStartupInfo.arguments = _processArgs;
_process = new NativeProcess();
_process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
_process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, progress);
_process.addEventListener(NativeProcessExitEvent.EXIT, onExit);
_process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOErrorNativeProcess);
_process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOErrorNativeProcess);
_process.start(_nativeProcessStartupInfo);
}
public function onIOErrorNativeProcess(event:IOErrorEvent):void
{
trace(event.toString());
}
public function onOutputData(event:ProgressEvent):void
{
trace("Got: ", _process.standardOutput.readUTFBytes(_process.standardOutput.bytesAvailable));
}
public function progress(e:ProgressEvent):void
{
trace(e);
}
public function onExit(e:NativeProcessExitEvent):void
{
trace(e);
}
I have tried with 720P video too by changing bit rate from 4500k to 2500k which is as per YouTube and it is working fine but with 1080P something not went as per expectation.
Here are the video details:
Resolution : 1920*1080
Data Rate : 3220kbps
FrameRate : 20
Thanks in advance
There is two problem with the following code.
In the "progress" function I am not reading actual log of the FFMPEG, have to update progress event like below.
public function progress(e:ProgressEvent):void
{
trace("Progress: ", _process.standardOutput.readUTFBytes(_process.standardOutput.bytesAvailable));
}
For now I have just traced the log and code is working properly in Debug mode after creating build issue has been happening and after that I have logged all the data in file and then even after creating build everything is working fine.
I don't know the exact reason behind it, but this solution help me for now.
Thanks
I am currently working on a basic utility software that has the ability to record Keyboard & Mouse input, save the input to a .txt file, and playback the data on a file. I am revising the program for added file and playback functionality. The problem I'm having is with the Robot.mousePress() method within the mouse movement method:
public static void executeMouseMovementData() {
mouseRobot.mousePress(InputEvent.BUTTON1_MASK);
for (int i=0; i < MouseDataHandler.mouseData.size(); i++) {
mouseRobot.moveMouse(MouseDataHandler.mouseData.get(i).getX(), MouseDataHandler.mouseData.get(i).getY());
mouseRobot.delay(MouseDataHandler.mouseData.get(i).getTimeElapsed());
}
mouseRobot.releaseMouse();
}
This program follows a basic sequence of events: 1 Data initialization, 2 Press mouse, 3 Move mouse, 4 Release mouse. Unlike another method I've successfully implemented, this method does not press the mouse at any time for no obvious reason. Mouse movement works beautifully with the playback feature. I just can't seem to get the Robot to execute any type of mouse event other than movement, even if I restructure the method.
I've tried editing the method to make sure the Robot doesn't press the mouse at the time in which the "playback" button on the GUI is pressed, as to not mess with the focus of the mouse event. The error likely isn't related to other aspects of the code, because everything else in the program runs smoothly. The object "mouseRobot" is an basic extension class of the Java.awt.Robot class with a basic interface for compound Robot mouse methods(), and I even directly call the mousePress method from the Robot class.
What could be the malfunction that occurs with within this method?
Solved. Improved the method in which mouse movements are handled to do one mouse movement per frame. The class can now accurately perform various checks and data changes in between mouse movements, while also allowing other classes to function without being held up from a lengthy for loop. The method in the question was extremely inefficient, impractical and basically acted as a 'while' loop.
public void handleMouseMovements() {
if (shouldAttemptToMoveMouse) {
if (!targetHasBeenReached(currentAdjustedX, currentAdjustedY, targetX, targetY)) {
if (!movementCreated) {
calculateDirection(startX, startY, targetX, targetY);
getLineIndexToUse();
initializeMoveData(repositoryFileIndex, fileIndex);
movementCreated = true;
firstTime = System.currentTimeMillis();
}
if (CMMI >= Main.mouseDataHandler.getSizeOfRepositoryIndex(repositoryFileIndex, fileIndex)){
CMMI =0;
loopMovement();
}
if (movementfileIndexTimeHasElapsed(repositoryFileIndex, fileIndex)) {
moveMouse(repositoryFileIndex, fileIndex);
CMMI++;
firstTime = System.currentTimeMillis();
}
}
else {
resetData();
}
}
}
public void moveMouse(int repositoryFileIndex, int fileIndex) {
currentX = MouseDataHandler.mdr.get(repositoryFileIndex).get(fileIndex).get(CMMI).getX();
currentY = MouseDataHandler.mdr.get(repositoryFileIndex).get(fileIndex).get(CMMI).getY();
currentAdjustedX = currentX + distanceX;
currentAdjustedY = currentY + distanceY;
Main.bot.moveMouse(currentAdjustedX + Main.getX(), currentAdjustedY + Main.getY() + 25);
}
This method is vastly more efficient and handles all criteria necessary to determine direction, determine file index of mouse data to be used, calculates target-file index offsets, and has proper time intervals inbetween mouse movements.
I am having some issues with AS3 Object Arrays. I am trying to make an inventory system, which the user can navigate left and right (which is working). When the user presses ENTER the item should then equip.
I was going to use switch and case to equip the items, as there will only be around 8 items to the game. I get the result [object purpleSword] when using trace, but my switch isn't getting any results or firing anything. I need the equipItem function to find the purpleSword that's ben found in the arrayItems. Items are added to the arrayItems when picked up off the floor.
Does anyone have any tips for using Objects for an RPG inventory system? Many thanks in advance.
public var arrayItems: Array = new Array();
if (keyEvent.keyCode == Keyboard.ENTER) {
if (currentScreen == "inventory") {
if(inventoryCurrent >= 0) {
var actualCurrentItem = inventoryCurrent - 1;
equipItem(arrayItems[actualCurrentItem]);
}
}
}
public function equipItem(itemNumber) {
switch(itemNumber) {
case "purpleSword":
trace("equip purple sword");
break;
}
}
AS3 has a type system, you should use it to help you understand your own errors, and help others understand your code (like us).
Given the fact that you say your output gives you [object purpleSword] I can assume you have a class purpleSword. My guess is that this is an exported symbol, not a .as class file, but it could be either.
But those are all guesses because you haven't provided any type information. For example:
arrayItems:Array could contain anything, and you haven't told us what. You could use a items:Vector.<Object> to store objects, or Vector.<Sprite> to store symbols exported from your Flash library, or better yet create an InventoryItem class and use a Vector.<InventoryItem> to store them.
var actualCurrentItem should be var actualCurrentItem:int
equipItem(itemNumber) should be equipItem(itemNumber:int):void?
If you do this, you will realize (either through your own observation or the compiler telling you) that your equipItem() function is wrong: it expects an itemNumber but it will receive an object.
If my prior assumptions were correct, you could do this:
public var items:Vector.<Object> = new <Object>[];
if (keyEvent.keyCode == Keyboard.ENTER) {
if (currentScreen == "inventory") {
if(inventoryCurrent >= 0) {
var actualCurrentItem:int = inventoryCurrent - 1;
equipItem(items[actualCurrentItem]);
}
}
}
public function equipItem(item:Object):void {
switch(item.constructor) {
case purpleSword:
trace("equip purple sword");
break;
}
}
This works because Object/constructor is a reference to the class of any object, ie purpleSword class, etc. However, you really should use something more concrete than Object, which could be any kind of object and tells you nothing about what kind of properties it might have.
My question is a bit vague so let me elaborate. I'm a beginner programmer working on my first flash game which for the point of this question is a side-scrolling platformer like mario for example. Unlike a traditional platformer though, the level will continue indefinitely until a player dies or quits the game. The level is tilebased and will be generated automatically through a array which specifies what object is in each tile( or 0 if there is no object). In order to ensure my game doesn't automatically crash from excessive objects I will generate more of the map( by creating new instances of objects) as the player progresses so that as the player move right the map is generated just past the edge of the screen.
Now back to the matter at hand, I'm guessing that once the player gets to a certain point in the game it will start to slow down because more and more objects are being created.
I assume the solution to this problem would be to remove the instances to the left of the screen as the player progresses however the problem with this is I need the player to have the ability to go back through the level.
So my question is: how can i 'delete' or remove the instances from memory, so my game doesn't slow down, but also restore the instance when the player moves into a certain proximity of where that instance is (or was).
Note: Currently aside from the player the only object i have in the game is the 'Wall' object all instances of which are stored in the 'Wallarray' array which i currently only use to reference instances of a Wall for collision detection
See my comment, but either way it may be the same answer. Read up on the SharedObject class and do some simple experiments using SharedObjects to write info about objects to disk, and to read that info back.
My suggestion is to split game model from its view. You'll have the whole level model stored in a separate class and a view which renders visible model's part onto the stage. Rendering engine will remove visual objects that are out of the screen as well as create visual objects which become visible. Your model will dispatch some events to notify your view about its changes. Hope that will help.
I suggest you to use object pooling: When your objects are not visible anymore you can put them in a temporary array an when you need a new object, instead of create a new you can get one from this array.
here an example of object with his pool:
package
{
public class Pooled extends MovieClip
{
/** the array containg objects created and not used **/
protected static var _pool :Vector.<Pooled>;
/** the number of objects in the pool **/
protected static var _nbItems :int;
public function Pooled()
{
}
/** a function to dispose the object **/
public function dispose():void
{
// do what you want here for release memory
}
/** the function to call to release the object and return it to the pool **/
public function release():void
{
// do what you want here, stop animations, remove from parent, remove listeners ...
// put it in the pool
_pool[_nbItems++] = this;
}
/** a static function to initialize the object and to create the pool **/
public static function init():void
{
_pool = new Vector.<Pooled>();
_nbItems = 0;
}
/** a static function to get an object from the pool **/
public static function get():Pooled
{
var a :Pooled;
if( _nbItems > 0 )
{
a = _pool.pop();
_nbItems--;
}
else
{
a = new Pooled();
}
return a;
}
/** a static function to destroy objects and the pool **/
public static function dispose():void
{
for( var i:int = 0; i<_nbItems; ++i ) _pool[i].dispose();
_pool.length = 0;
_pool = null;
}
}
}
You have to call first the static init method to create the pool array.
After that instead of create object using new Pooled();, use Pooled.get();, it will return you item from the pool if available and if not, it will create a new one.
When you don't want your object anymore, you can call release() function and the object will be moved to the pool.
Using this technique, the maximum object in memory will be the maximum displayed object at the same time. And you avoid the time of creating new objects when your pool contain object.
Hope this could help you.
The Sound API seems to be missing a function to indicate that a sound is finished playing. Is there some other way of finding out if the sound is done?
Not without submitting a patch to libgdx as far as I know the underlying Sound Backends for both OpenAL and Android don't even track the information internally, though the Music API has an isPlaying() function and getPosition() function as per the documentation.
just set this
sound.setLooping(false);
this way it will not run again and again.
and to check whether sound is playing or
not do this.
make a boolean variable
boolean soundplaying;
in render method do this
if(sound.isPlaying()){
soundplaying =true
}
and make a log
gdx.app.log("","sound"+soundplaying);
You can track this by storing the sound instance id that e.g. play() and loop() return. Example code:
private Sound sound;
private Long soundId;
...
public void startSound() {
if (soundId != null) {
return;
}
soundId = sound.loop(); // or sound.play()
}
public void stopSound() {
sound.stop(soundId);
soundId = null;
}
If you didn't want to have to call stopSound() from client code, you could just call it from startSound() instead of the return, to ensure any previous sound is stopped.