I wanted to create something like jetboy asteroids that I found on android samples but i'ts too complicated to get the right code and to make it work properly.
I don't want on touch simply the asteroids should begin themselves.
Can someone link me some good stuff or give me some examples?
private void doAsteroidCreation() {
// Log.d(TAG, "asteroid created");
Asteroid _as = new Asteroid();
int drawIndex = mRandom.nextInt(4);
// TODO Remove hard coded value
_as.mDrawY = mAsteroidMinY + (drawIndex * 63);
_as.mDrawX = (mCanvasWidth - mAsteroids[0].getWidth());
_as.mStartTime = System.currentTimeMillis();
mDangerWillRobinson.add(_as);
}
Related
I have created an android application similar to Not Tetris 2 using Libgdx with Box2d.
It can successfully remove a slice from the world, which obviously involves duplicating several bodies and destroying/creating fixtures. However, seemingly at random, a body with a 2x2 fixture will appear. The body and fixture are displayed using information related to the objects around it when it is created, so I narrowed its creation down to the following function:
Body duplicateBody(Body original){
BodyDef d = new BodyDef();
d.position.set(original.getPosition());
d.angle = original.getAngle();
d.linearVelocity.set(original.getLinearVelocity());
d.angularVelocity = original.getAngularVelocity();
Body dup = world.createBody(d);
dup.setType(BodyDef.BodyType.DynamicBody);
return dup;
}
I use this function in 2 different contexts:
Making a copy of the body if a "slice" cuts one in two -- I then transfer the fixtures which are below to it.
When a fixture is below the line then it is added to a body created for ones below
Making a copy of the body when groups of fixtures are separated
I commented out the code responsible for the third instance and still had the 2x2 boxes spawning, so here are the functions relevant to the others:
...
if (below && !above) {
//copy fixture, add copy to lower body and remove original
Body top = fixture.getBody();
FixtureDef n = new FixtureDef();
PolygonShape s = new PolygonShape();
s.set(getLocalVerticesOfFixture(fixture));
n.shape = s;
n.density = fixture.getDensity();
//create lower body if a lower one doesn't already exist
if (!topBottomPairs.containsKey(top)) {
Body dup = duplicateBody(top);
topBottomPairs.put(top, dup);
}
//delete fixture
remove.add(fixture);
Fixture f = topBottomPairs.get(top).createFixture(n);
s.dispose();
}
...
if (below && above) {
//copy fixture, add copy to lower body, but keep original on upper as it needs to split
FixtureDef n = new FixtureDef();
PolygonShape s = new PolygonShape();
s.set(getLocalVerticesOfFixture(fixture));
n.shape = s;
n.density = fixture.getDensity();
Body top = fixture.getBody();
//create lower body if a lower one doesn't already exist
if (!topBottomPairs.containsKey(top)) {
Body dup = duplicateBody(top);
topBottomPairs.put(top, dup);
}
Fixture second = topBottomPairs.get(top).createFixture(n);
s.dispose();
}
....
private Vector2[] getLocalVerticesOfFixture(Fixture fixture) {
PolygonShape shape = ((PolygonShape) fixture.getShape());
Vector2[] localVertices = new Vector2[shape.getVertexCount()];
for (int i = 0; i < shape.getVertexCount(); i++) {
localVertices[i] = new Vector2();
shape.getVertex(i, localVertices[i]);
}
return localVertices;
}
I also have this remove fixture function which runs on all fixtures I want to remove:
private void smartDeleteFixture(Fixture f){
f.getBody().destroyFixture(f);
if(f.getBody().getFixtureList().size == 0){
world.destroyBody(f.getBody());
}
}
Nowhere do I create vertices, let alone a fixture of a 2x2 shape. I was wondering if this duplication function has any flaws, or if I stumbled upon some "default shape" that box2d uses.
Edit: I have removed anything not related to the manipulation of box2d bodies. Hope that helps
Deleted this question as I decided to perform a major recode and hoped that would fix my problem. It did not, but I figured out the cause.
I looked through box2d and found a couple instances of code similar to this in the polygon shape class:
if (n < 3)
{
// Polygon is degenerate.
b2Assert(false);
SetAsBox(1.0f, 1.0f);
return;
}
These instances check the number of vertices after various operations and turn the shape into a 2x2 box if there are fewer than 3. One of these operations makes the shape convex. Another checks if vertices are close together (closer than 0.0025f), deleting one if so.
In my case, the problem was simple. Some of my vertices were less than 0.0025f from each other, resulting in them being deleted, the vert count dropping below 3, an assertion being ignored, and then my shape being turned into a 2x2 box. I hope this helps someone out.
[also posted on MPAndroidChart's Github]
I need realtime graph with a rolling windows, that's when I ran into 'problems'. Adding data is no problem, but after adding data with an Xvalue(index) that's higher than the current width of the graph the graph doesn't autoscroll because it don't seem to be able to always display [X] Xvalues.
Example of issue:
The result in graph 3 is not what I want for displaying realtime data. A scrollingwindow is much more usefull. So I tried to archieve this..
My working 'solution' was to remove the first Xvalue, add a new one and move all Xindexes of all Entries on screen one to the left. The result is some code like this:
int GRAPH_WIDTH = 10;
LineData lineData = chart.getData();
LineDataSet lineDataSet = lineData.getDataSetByIndex(0);
int count = lineDataSet.getEntryCount();
// Make rolling window
if (lineData.getXValCount() <= count) {
// Remove/Add XVal
lineData.getXVals().add("" + count);
lineData.getXVals().remove(0);
// Move all entries 1 to the left..
for (int i=0; i < count; i++) {
Entry e = lineDataSet.getEntryForXIndex(i);
if (e==null) continue;
e.setXIndex(e.getXIndex() - 1);
}
// Set correct index to add value
count = GRAPH_WIDTH;
}
// Add new value
lineData.addEntry(new Entry([random value], count), 0);
// Make sure to draw
chart.notifyDataSetChanged();
chart.invalidate();
This works quite well actually (as seen in this video here ), but I feel like there must be an easier way to do this. Maybe I overlooked some API window/scrolling..
But if this is the 'right' way to archieve this result then it would be an enhancement to add support for this kind of graphs in your library.
Thank you for the video.
I am surprised you found a workaround that is rather complicated but works quite well.
Unfortunately this is currently the only way to achieve what you want. I will work on making this easier soon probably reusing some of your code.
Also take a look at these two methods:
setScaleMinima(...)
centerViewPort(...)
I took your code and changed it a bit. It will only show up to GRAPH_WIDTH number of points at a time. Then it scrolls along deleting the older data. Useful if you're only interested in relatively recent data. Is that what you were going for?
public void addTimeEntry() {
String entry_date_time = new SimpleDateFormat("MMM d - HH:mm:ss").format(new Date());
LineData lineData = mChart.getData();
int GRAPH_WIDTH = 15;
if (lineData != null) {
LineDataSet set = lineData.getDataSetByIndex(0);
if (set == null) {
set = createSet();
lineData.addDataSet(set);
}
// Make rolling window
if (lineData.getXValCount() > GRAPH_WIDTH) {
lineData.getXVals().remove(0);
set.removeEntry(0);
lineData.getXVals().add(entry_date_time);
lineData.addEntry(new Entry((float) (Math.random() * 40) + 30f, GRAPH_WIDTH), 0);
// lineData.getXVals().add(entry_date_time);
// Move all entries 1 to the left..
for (int i=0; i < set.getEntryCount(); i++) {
Entry e = set.getEntryForXIndex(i);
if (e==null) continue;
e.setXIndex(e.getXIndex() - 1);
}
}
else{
lineData.getXVals().add(entry_date_time);
lineData.addEntry(new Entry((float) (Math.random() * 40) + 30f, lineData.getXValCount()-1), 0);
}
// let the chart know it's data has changed
mChart.notifyDataSetChanged();
mChart.invalidate();
}
}
quick question. I am developing a top-down 2d Platformer game with lots of enemies in the map (at least a hundred spawn at the start of each level). Each enemy uses an AI that searches the map for objects with a specified tag, sorts each object into a list based on their distance, then reacts to the object closest to them.
My code works, but the thing is, if the machine my game is running on is slow, then my game lags. I want to be able to port my game to Android and iOS with low end specs.
In pursuit of putting less strain on the CPU, is there a better way to write my AI?
Here is my code:
void Start () {
FoodTargets = new List<Transform>(); // my list
SelectedTarget = null; // the target the enemy reacts to
myTransform = transform;
AddAllFood ();
}
public void AddAllFood()
{
GameObject[] Foods = GameObject.FindGameObjectsWithTag("Object");
foreach (GameObject enemy in Foods)
AddTarget (enemy.transform);
}
public void AddTarget(Transform enemy)
{
if (enemy.GetComponent<ClassRatingScript>().classrating != 1) { // classrating is an attribute each enemy has that determines their identity (like if they are a plant, a herbivore or a carnivore)
FoodTargets.Add (enemy); // adds the object to the list
}
}
private void SortTargetsByDistance() // this is how I sort according to distance, is this the fastest and most efficient way to do this?
{
FoodTargets.Sort (delegate(Transform t1, Transform t2) {
return Vector3.Distance(t1.position, myTransform.position).CompareTo(Vector3.Distance(t2.position, myTransform.position));
});
}
private void TargetEnemy() // this is called every 4 frames
{
if (SelectedTarget == null) {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
else {
SortTargetsByDistance ();
SelectedTarget = FoodTargets [1];
}
}
if (optimizer <= 2) { // this is a variable that increments every frame and resets to 0 on the 3rd frame. Only every 3rd frame is the target enemy method is called.
optimizer++;
} else {
TargetEnemy ();
// the rest are attributes that the AI considers when reacting to their target
targetmass = SelectedTarget.GetComponent<MassScript> ().mass;
targetclass = SelectedTarget.GetComponent<ClassRatingScript> ().classrating;
mass = this.GetComponent<MassScript> ().mass;
classrating = this.GetComponent<ClassRatingScript> ().classrating;
distance = Vector3.Distance (transform.position, SelectedTarget.transform.position);
optimizer = 0;
}
Is there a more optimized way of doing this? Your help will be much appreciated. Thanks in advance!
I'm not awfully familiar with C# or Unity but I would look very carefully at what sorting algorithm your sorting method is using. If all you want is the closest Game Object, then sorting isn't necessary.
The fastest sorting algorithms, such as Quicksort, are O(n*log(n)). That is to say that the time it takes to sort a collection of n objects is bounded by some constant multiple of n*log(n). If you just want the k closest objects, where k << n, then you can perform k iterations of the Bubble Sort algorithm. This will have time-complexity O(k*n), which is much better then before.
However, if you only need the single closest object, then just find the closest object without sorting (pseudocode):
float smallestDistance = Inf;
object closestObject = null;
foreach object in objectsWithTag {
float d = distance(object, enemy);
if (d < smallestDistance) {
smallestDistance = d;
closestObject = object;
}
}
This extremely simple algorithm has time complexity O(n).
New to Starling-Feathers, before I start to develop my mobile app, I would like to know what are the best practice to develop the following features using Feathers:
Partial view slide - A part of the next view is shown and the user can drag to see it all. Could this be done with Feathers ScreenNavigator?
Sliding menu from the top
Dragging text elements with title pushing the last items
Since it is hard to describe I've added an animated gif to describe my goals. Thanks for all your advices
I would like to maximize the use of Feathers built in widgets and will appreciate code examples :)
I think these are not that much hard to do in core flash or you can also do it in Starling feathers too. YOu can use list item to do the third point (Dragging text elements with title pushing the last items) .
First and second you can use it with tweening effect i think.
For the third one using feathers list.
(re formated post)
private function addFeatherList():void{
Flist = new List();
Flist.width = 250;
Flist.height = 300;
Flist.x = GAME_W/2 - Flist.width/2;
Flist.y = sampText.height + 5;
this.addChild( Flist );
fontArr = Font.enumerateFonts(true);
for (var i:int=0; i<fontArr.length; i++){
ListArr[i] = { text:Font(fontArr[i]).fontName }
}
var groceryList:ListCollection = new ListCollection( ListArr );
Flist.dataProvider = groceryList;
Flist.itemRendererProperties.labelField = "text";
FeathersControl.defaultTextRendererFactory=function():ITextRenderer{
var render:TextFieldTextRenderer=new TextFieldTextRenderer();
render.textFormat = new TextFormat("Verdana",8,0xFFFFFF,false);
return render;
}
Flist.itemRendererFactory = function():IListItemRenderer //list.itemRendererProperties.accessorySourceField list.itemRendererFactory
{
var renderer:DefaultListItemRenderer = new DefaultListItemRenderer();
renderer.addEventListener(Event.TRIGGERED, onListTriggered);
return renderer;
}
}
I have a 10-field average lap calculator. However, in testing, someone said they normally only run X laps in practice, vs. 10 (let's say 7).
I think I could use an if statement, but there'd be at least 10 of them and a bunch of clumsy code, and I'm not sure on arrays/switch statements exactly. I think all of those might be possible, but my low level of experience has yet to fully comprehend these useful tools.
CURRENT CODE:
double tenLapAvgVar = ((lap1Var + lap2Var + lap3Var + lap4Var + lap5Var + lap6Var + lap7Var + lap8Var + lap9Var + lap10Var) / 10);
So essentially, if someone leaves a field or fields blank, I want to calculate the average based on the populated fields, not 10 (if they leave 3 fields blank, calculate based on 7, for instance). Any help you guys could provide would be much appreciated, thanks!
You could have an ArrayList<EditText> object and a method which iterates over it and adds up the values. Something like:
public double getLapAverage()
{
int noOfCompletedLaps = 0;
double lapAve = 0;
double lapsTotal = 0;
for(EditText text : textBoxes)
{
if(text.getText().toString().length() > 0)
{
//psuedo code, and assuming text is numerical
lapsTotal += Double.parse(text.getText().toString());
noOfCompletedLaps++;
}
}
if( noOfCompletedLaps > 0)
{
lapAve = lapsTotal / noOfCompletedLaps;
}
return lapAve;
}
Maybe it would be better if you used an array instead of 10 different variables.
Then you can use a for statement and initialize them to 0, afterwords let the user fill the array and count how many are not zero.
Finally sum up all the array and divide by the count you previously calculated.