I am getting the error as
android.view.InflateException: Binary XML file line #16: Error inflating class DrawView
. I am creating customize view in DrawView class. In Oncreate method while calling setContentView(R.layout.newimage_activity); it will show me above error.
XML layout is:
<com.capricorn.RayMenu
android:id="#+id/ray_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<com.element45.android.camera.activities.DrawView
android:id="#+id/CustomView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
tools:context="com.element45.android.camera.activities.newImage_Activity"
/>
And DrawView Class code is:
public class DrawView extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private Paint mPaint;
private RectF rectF ;
private Region Region1;
private Region Region2;
private List<Point> mPoints;
private List<Line> mLines;
private boolean bModify_line;
private float mX, mY;
private float mOriginal_X, mOriginal_Y;
private Line mLine ;
private static final float TOUCH_TOLERANCE = 50;
public DrawView(Context c)
{
super(c);
rectF = new RectF();
mPath = new Path();
mPath.computeBounds(rectF, true);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
mPaint.setXfermode(null);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPoints = new ArrayList<Point>();
mLines = new ArrayList<Line>();
bModify_line = false;
}
int width,height;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w ; height =h;
}
#Override
protected void onDraw(Canvas canvas)
{
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
canvas.drawColor(0xFFAAAAAA);//original color 0xFFAAAAAA
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for(int i = 0 ; i < mLines.size();i++)
{
Line line = mLines.get(i);
mCanvas.drawLine(line.getStartPoint().x, line.getStartPoint().y, line.getEndPoint().x, line.getEndPoint().y, mPaint);
}
}
private void touch_move(float x, float y)
{
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
mX = x;
mY = y;
}
}
private void touch_start(float x, float y)
{
int iLineNumber = checkPointinLines(x, y);
if(iLineNumber >= 0 )
{
bModify_line = true;
mPath.moveTo(x, y);
mX = x;
mY = y;
}
else
{
mLine = new Line();
mLine.setStartPoint(new Point((int)x, (int)y));
mPath.moveTo(x, y);
mX = x;
mY = y;
}
mOriginal_X = mX;
mOriginal_Y = mY;
}
private void touch_up()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
if(iPoint == 0)
{
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point((int)mX, (int)mY));
}
else if(iPoint == 1)
{
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point((int)mX, (int)mY));
}
mLines.set(iLineNumber, line);
System.out.println("After setline size of lineArray::"+mLines.size());
bModify_line = false;
}
}
}
else
{
mPath.lineTo(mX, mY);
mLine.setEndPoint(new Point((int)mX, (int)mY));
mLines.add(mLine);
mPath.reset();
}
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
/**
* Checks if user touch point with some tolerance
*/
private int checkPointOnLine(float x, float y,Line line)
{
int iPoint = -1;
Point point = line.getStartPoint();
if(x > (point.x - TOUCH_TOLERANCE) && x < (point.x + TOUCH_TOLERANCE) && y > (point.y - TOUCH_TOLERANCE) && y < (point.y + TOUCH_TOLERANCE) )
iPoint = 0;
point = line.getEndPoint();
if (x > (point.x - TOUCH_TOLERANCE) && x < (point.x + TOUCH_TOLERANCE) && (y > (point.y - TOUCH_TOLERANCE) && y < (point.y + TOUCH_TOLERANCE) ))
iPoint = 1 ;
return iPoint;
}
private int checkPointinLines(float x, float y)
{
int iLine = -1;
for(int i=0 ;i < mLines.size();i++)
{
Line line = mLines.get(i);
if(x > (line.getStartPoint().x - TOUCH_TOLERANCE)
&& x < (line.getStartPoint().x + TOUCH_TOLERANCE)
&& y > (line.getStartPoint().y - TOUCH_TOLERANCE)
&& y < (line.getStartPoint().y + TOUCH_TOLERANCE)
||
x > (line.getEndPoint().x - TOUCH_TOLERANCE)
&& x < (line.getEndPoint().x + TOUCH_TOLERANCE)
&& y > (line.getEndPoint().y - TOUCH_TOLERANCE)
&& y < (line.getEndPoint().y + TOUCH_TOLERANCE))
iLine = i;
}
return iLine;
}
public void movePoint(int position)
{
switch(position)
{
case 0:
//up
movePointUp();
break;
case 1:
//Right
movePointRight();
break;
case 2:
//Down
movePointDown();
break;
case 3:
//Left
movePointLeft();
break;
}
}
private void movePointUp()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x ;
modifyPointY = line.getStartPoint().y - 2;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x;
modifyPointY = line.getEndPoint().y -2;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
private void movePointRight()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x + 2;
modifyPointY = line.getStartPoint().y ;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x + 2;
modifyPointY = line.getEndPoint().y ;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
private void movePointLeft()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x - 2 ;
modifyPointY = line.getStartPoint().y ;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x - 2;
modifyPointY = line.getEndPoint().y ;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
private void movePointDown()
{
if(bModify_line)
{
int iLineNumber = checkPointinLines(mOriginal_X, mOriginal_Y);
if(iLineNumber > -1)
{
Line line = mLines.get(iLineNumber);
int iPoint = checkPointOnLine(mX,mY,line);
if(iPoint >= 0)
{
int modifyPointX,modifyPointY;
if(iPoint == 0)
{
modifyPointX = line.getStartPoint().x ;
modifyPointY = line.getStartPoint().y + 2;
mPath.moveTo(line.getEndPoint().x, line.getEndPoint().y);
line.setStartPoint(new Point(modifyPointX, modifyPointY));
}
else if(iPoint == 1)
{
modifyPointX = line.getEndPoint().x;
modifyPointY = line.getEndPoint().y + 2;
mPath.moveTo(line.getStartPoint().x, line.getStartPoint().y);
line.setEndPoint(new Point(modifyPointX, modifyPointY));
}
mLines.set(iLineNumber, line);
bModify_line = false;
}
}
}
else
{
Toast.makeText(getContext(), "Please select point", Toast.LENGTH_SHORT).show();
}
}
}
for the xml inflation you need to override the constructor that takes Context and AttributeSet as parameter. From the documentation
Constructor that is called when inflating a view from XML.
Add
public DrawView(Context c, AttributeSet attrs) {
super(c, attrs);
}
to your custom view. You could have a common init() method that you share between the two constructors where you perform your initialization (in order to avoid code duplicates)
Related
Currently i'm using LWJGL to make a 2D game. But I've run into an issue. I am trying to make an "infinite world" but an issue comes up because if I create a lot of objects the frames drop and I believe it has to do with the amount of textures being loaded to objects.
Currently I'm creating my world in a grid fashion like this
for(int x = -WORLDWIDTH; x < WORLDWIDTH; x+= BW)
{
for(int y = -WORLDHEIGHT; y < WORLDHEIGHT; y += BH)
{
Tile newTile = new Tile(x,y,BW,BH,TileType.Grass);
tiles.add(newTile);
}
}
Where BW and BH are the block width and height. I try to keep texture loading to only objects on screen using this if statement
if(x >= 0-BW && x + width < WIDTH+BW && y >= 0-BH && y+ height < HEIGHT+BH)
{
DrawQuadTexRotate(getTexture(), getX(), getY(), getWidth(),getHeight(),angle);
}
To load textures I do this
public static void DrawQuadTexRotate(Texture tex, float x, float y, float width, float height, float angle)
{
tex.bind();
glTranslatef(x + width / 2, y + height / 2, 0);
glRotatef(angle, 0 ,0 , 1);
glTranslatef(- width / 2, - height / 2, 0);
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(0,0);
glTexCoord2f(1,0);
glVertex2f(width,0);
glTexCoord2f(1,1);
glVertex2f(width,height);
glTexCoord2f(0,1);
glVertex2f(0,height);
glEnd();
glLoadIdentity();
}
public static Texture LoadTexture(String path, String fileType)
{
Texture tex = null;
InputStream in = ResourceLoader.getResourceAsStream(path);
try {
tex = TextureLoader.getTexture(fileType, in);
} catch (IOException e) {
e.printStackTrace();
}
return tex;
}
The Tile class basically has methods to do certain things based on what type it is. It holds the width, height, x, y and texture which my DrawQuadTex method uses
Here is the tile class
public class Tile {
public float x, y, width, height, angle;
private Texture texture;
private TileType type;
public long timeStart = 0;
public int filled = 1;
public int power = 0;
public int transmitPower = 0;
int connected = 0;
public boolean moveRight,moveLeft,moveUp,moveDown,moveAngle;
public Tile(float x, float y, float width, float height,TileType type)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.type = type;
this.texture = QuickLoad(type.textureName);
timeStart = Timer.getTime();
updateType();
updateFill();
}
public void draw()
{
if(x >= 0-BW && x + width < WIDTH+BW && y >= 0-BH && y+ height < HEIGHT+BH)
{
DrawQuadTexRotate(getTexture(), getX(), getY(), getWidth(),getHeight(),angle);
}
}
public void addFood()
{
if(this.type == TileType.Farm && filled == 1)
{
long timing = Timer.getTime();
if(timing >= (timeStart + 10000))
{
Values.food += (1+Artist.riverAmount);
timeStart = timing;
}
}
}
public void mineOre()
{
if(this.type == TileType.Mine && filled == 1)
{
long timing = Timer.getTime();
if(timing >= (timeStart + 20000))
{
for(int i = 0; i < tiles.size();i++)
{
if(tiles.get(i).getType() == TileType.Ore)
{
tiles.get(i).setType(TileType.LandTile);
Values.oreAmount += 1;
timeStart = timing;
break;
}
}
}
}
}
public void move()
{
if(moveRight == true)
{
x -= 10;
}
if(moveLeft == true)
{
x += 10;
}
if(moveUp == true)
{
y += 10;
}
if(moveDown == true)
{
y -= 10;
}
}
public void testPower()
{
for(int i = 0; i < tiles.size(); i++)
{
if(tiles.get(i).x >= x - BW && tiles.get(i).x <= x + BW && tiles.get(i).y >= y - BH && tiles.get(i).y <= y + BH && tiles.get(i).getType() == TileType.Wire && tiles.get(i).transmitPower == 1 && type == TileType.HomeBasic)
{
power = 1;
break;
}
else
{
power = 0;
}
if(tiles.get(i).x >= x - BW && tiles.get(i).x <= x + BW && tiles.get(i).y >= y - BH && tiles.get(i).y <= y + BH && (tiles.get(i).transmitPower == 1 || tiles.get(i).type == TileType.PowerPlant) && type == TileType.Wire)
{
transmitPower = 1;
break;
}
else if(tiles.get(i).type == TileType.Wire && tiles.get(i).transmitPower == 0)
{
transmitPower = 0;
}
else
{
transmitPower = 0;
}
}
}
public void updateFill()
{
if(type == TileType.HomeBasic || type == TileType.Farm || type == TileType.Mine)
{
filled = 0;
}
}
public void stats()
{
if(type == TileType.HomeBasic)
{
//wt.drawString((int)x, (int)(y-25), Integer.toString(filled), Color.white);
}
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public TileType getType() {
return type;
}
public void setType(TileType type) {
this.type = type;
updateType();
}
public void updateType()
{
this.texture = QuickLoad(type.textureName);
timeStart = Timer.getTime();
updateFill();
}
}
public static Texture QuickLoad(String name)
{
Texture tex = null;
tex = LoadTexture("res/" + name + ".png", "PNG");
return tex;
}
So how would I go about trying to fix this?
I have a program that creates a Grid and rearranges it by drag-and-droping, first of all everything is functional BUT not the way I wanted it. The must common rearrange is this, you drag an object and when you drop it falls into that position moving all the rest forward until they find the empty space, what I want is more simple; I want the objects to switch with the one that's in the position you dropped it. This is the code of the adapter:
#SuppressLint("WrongCall")
public class DragGridView extends ViewGroup implements View.OnTouchListener,
View.OnClickListener, View.OnLongClickListener {
public static float childRatio = .9f;
protected int colCount, childSize, padding, dpi, scroll = 0;
protected float lastDelta = 0;
protected Handler handler = new Handler();
protected int dragged = -1, lastX = -1, lastY = -1, lastTarget = -1;
protected boolean enabled = true, touching = false;
public static int animT = 150;
protected ArrayList<Integer> newPositions = new ArrayList<Integer>();
protected OnRearrangeListener onRearrangeListener;
protected OnClickListener secondaryOnClickListener;
private OnItemClickListener onItemClickListener;
public interface OnRearrangeListener {
public abstract void onRearrange(int oldIndex, int newIndex);
}
public DragGridView(Context context, AttributeSet attrs) {
super(context, attrs);
setListeners();
handler.removeCallbacks(updateTask);
handler.postAtTime(updateTask, SystemClock.uptimeMillis() + 500);
setChildrenDrawingOrderEnabled(true);
DisplayMetrics metrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(metrics);
dpi = metrics.densityDpi;
}
protected void setListeners() {
setOnTouchListener(this);
super.setOnClickListener(this);
setOnLongClickListener(this);
}
#Override
public void setOnClickListener(OnClickListener l) {
secondaryOnClickListener = l;
}
protected Runnable updateTask = new Runnable() {
public void run() {
if (dragged != -1) {
if (lastY < padding * 3 && scroll > 0)
scroll -= 20;
else if (lastY > getBottom() - getTop() - (padding * 3)
&& scroll < getMaxScroll())
scroll += 20;
} else if (lastDelta != 0 && !touching) {
scroll += lastDelta;
lastDelta *= .9;
if (Math.abs(lastDelta) < .25)
lastDelta = 0;
}
clampScroll();
onLayout(true, getLeft(), getTop(), getRight(), getBottom());
handler.postDelayed(this, 25);
}
};
#Override
public void addView(View child) {
super.addView(child);
newPositions.add(-1);
};
#Override
public void removeViewAt(int index) {
super.removeViewAt(index);
newPositions.remove(index);
};
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// compute width of view, in dp
float w = (r - l) / (dpi / 160f);
colCount = 2;
int sub = 240;
w -= 280;
while (w > 0) {
colCount++;
w -= sub;
sub += 40;
}
childSize = (r - l) / colCount;
childSize = Math.round(childSize * childRatio);
padding = ((r - l) - (childSize * colCount)) / (colCount + 1);
for (int i = 0; i < getChildCount(); i++)
if (i != dragged) {
Point xy = getCoorFromIndex(i);
getChildAt(i).layout(xy.x, xy.y, xy.x + childSize,
xy.y + childSize);
}
}
#Override
protected int getChildDrawingOrder(int childCount, int i) {
if (dragged == -1)
return i;
else if (i == childCount - 1)
return dragged;
else if (i >= dragged)
return i + 1;
return i;
}
public int getIndexFromCoor(int x, int y) {
int col = getColOrRowFromCoor(x), row = getColOrRowFromCoor(y + scroll);
if (col == -1 || row == -1)
return -1;
int index = row * colCount + col;
if (index >= getChildCount())
return -1;
return index;
}
protected int getColOrRowFromCoor(int coor) {
coor -= padding;
for (int i = 0; coor > 0; i++) {
if (coor < childSize)
return i;
coor -= (childSize + padding);
}
return -1;
}
protected int getTargetFromCoor(int x, int y) {
if (getColOrRowFromCoor(y + scroll) == -1)
return -1;
int leftPos = getIndexFromCoor(x - (childSize / 4), y);
int rightPos = getIndexFromCoor(x + (childSize / 4), y);
if (leftPos == -1 && rightPos == -1)
return -1;
if (leftPos == rightPos)
return -1;
int target = -1;
if (rightPos > -1)
target = rightPos;
else if (leftPos > -1)
target = leftPos + 1;
if (dragged < target)
return target - 1;
return target;
}
protected Point getCoorFromIndex(int index) {
int col = index % colCount;
int row = index / colCount;
return new Point(padding + (childSize + padding) * col, padding
+ (childSize + padding) * row - scroll);
}
public int getIndexOf(View child) {
for (int i = 0; i < getChildCount(); i++)
if (getChildAt(i) == child)
return i;
return -1;
}
public void onClick(View view) {
if (enabled) {
if (secondaryOnClickListener != null)
secondaryOnClickListener.onClick(view);
if (onItemClickListener != null && getLastIndex() != -1)
onItemClickListener.onItemClick(null,
getChildAt(getLastIndex()), getLastIndex(),
getLastIndex() / colCount);
}
}
public boolean onLongClick(View view) {
if (!enabled)
return false;
int index = getLastIndex();
if (index != -1) {
dragged = index;
animateDragged();
return true;
}
return false;
}
#SuppressLint("WrongCall")
public boolean onTouch(View view, MotionEvent event) {
int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
enabled = true;
lastX = (int) event.getX();
lastY = (int) event.getY();
touching = true;
break;
case MotionEvent.ACTION_MOVE:
int delta = lastY - (int) event.getY();
if (dragged != -1) {
// change draw location of dragged visual
int x = (int) event.getX(), y = (int) event.getY();
int l = x - (3 * childSize / 4), t = y - (3 * childSize / 4);
getChildAt(dragged).layout(l, t, l + (childSize * 3 / 2),
t + (childSize * 3 / 2));
// check for new target hover
int target = getTargetFromCoor(x, y);
if (lastTarget != target) {
if (target != -1) {
animateGap(target);
lastTarget = target;
}
}
} else {
scroll += delta;
clampScroll();
if (Math.abs(delta) > 2)
enabled = false;
onLayout(true, getLeft(), getTop(), getRight(), getBottom());
}
lastX = (int) event.getX();
lastY = (int) event.getY();
lastDelta = delta;
break;
case MotionEvent.ACTION_UP:
if (dragged != -1) {
View v = getChildAt(dragged);
if (lastTarget != -1)
reorderChildren();
else {
Point xy = getCoorFromIndex(dragged);
v.layout(xy.x, xy.y, xy.x + childSize, xy.y + childSize);
}
v.clearAnimation();
if (v instanceof ImageView)
((ImageView) v).setAlpha(255);
lastTarget = -1;
dragged = -1;
}
touching = false;
break;
}
if (dragged != -1)
return true;
return false;
}
protected void animateDragged() {
View v = getChildAt(dragged);
int x = getCoorFromIndex(dragged).x + childSize / 2, y = getCoorFromIndex(dragged).y
+ childSize / 2;
int l = x - (3 * childSize / 4), t = y - (3 * childSize / 4);
v.layout(l, t, l + (childSize * 3 / 2), t + (childSize * 3 / 2));
AnimationSet animSet = new AnimationSet(true);
ScaleAnimation scale = new ScaleAnimation(.667f, 1, .667f, 1,
childSize * 3 / 4, childSize * 3 / 4);
scale.setDuration(animT);
AlphaAnimation alpha = new AlphaAnimation(1, .5f);
alpha.setDuration(animT);
animSet.addAnimation(scale);
animSet.addAnimation(alpha);
animSet.setFillEnabled(true);
animSet.setFillAfter(true);
v.clearAnimation();
v.startAnimation(animSet);
}
protected void animateGap(int target) {
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
if (i == dragged)
continue;
int newPos = i;
if (dragged < target && i >= dragged + 1 && i <= target)
newPos--;
else if (target < dragged && i >= target && i < dragged)
newPos++;
int oldPos = i;
if (newPositions.get(i) != -1)
oldPos = newPositions.get(i);
if (oldPos == newPos)
continue;
Point oldXY = getCoorFromIndex(oldPos);
Point newXY = getCoorFromIndex(newPos);
Point oldOffset = new Point(oldXY.x - v.getLeft(), oldXY.y
- v.getTop());
Point newOffset = new Point(newXY.x - v.getLeft(), newXY.y
- v.getTop());
TranslateAnimation translate = new TranslateAnimation(
Animation.ABSOLUTE, oldOffset.x, Animation.ABSOLUTE,
newOffset.x, Animation.ABSOLUTE, oldOffset.y,
Animation.ABSOLUTE, newOffset.y);
translate.setDuration(animT);
translate.setFillEnabled(true);
translate.setFillAfter(true);
v.clearAnimation();
v.startAnimation(translate);
newPositions.set(i, newPos);
}
}
protected void reorderChildren() {
if (onRearrangeListener != null)
onRearrangeListener.onRearrange(dragged, lastTarget);
ArrayList<View> children = new ArrayList<View>();
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).clearAnimation();
children.add(getChildAt(i));
}
removeAllViews();
while (dragged != lastTarget)
if (lastTarget == children.size())
{
children.add(children.remove(dragged));
dragged = lastTarget;
} else if (dragged < lastTarget)
{
Collections.swap(children, dragged, dragged + 1);
dragged++;
} else if (dragged > lastTarget)
{
Collections.swap(children, dragged, dragged - 1);
dragged--;
}
for (int i = 0; i < children.size(); i++) {
newPositions.set(i, -1);
addView(children.get(i));
}
onLayout(true, getLeft(), getTop(), getRight(), getBottom());
}
#SuppressLint("WrongCall")
public void scrollToTop() {
scroll = 0;
}
public void scrollToBottom() {
scroll = Integer.MAX_VALUE;
clampScroll();
}
protected void clampScroll() {
int stretch = 3, overreach = getHeight() / 2;
int max = getMaxScroll();
max = Math.max(max, 0);
if (scroll < -overreach) {
scroll = -overreach;
lastDelta = 0;
} else if (scroll > max + overreach) {
scroll = max + overreach;
lastDelta = 0;
} else if (scroll < 0) {
if (scroll >= -stretch)
scroll = 0;
else if (!touching)
scroll -= scroll / stretch;
} else if (scroll > max) {
if (scroll <= max + stretch)
scroll = max;
else if (!touching)
scroll += (max - scroll) / stretch;
}
}
protected int getMaxScroll() {
int rowCount = (int) Math.ceil((double) getChildCount() / colCount), max = rowCount
* childSize + (rowCount + 1) * padding - getHeight();
return max;
}
public int getLastIndex() {
return getIndexFromCoor(lastX, lastY);
}
public void setOnRearrangeListener(OnRearrangeListener l) {
this.onRearrangeListener = l;
}
public void setOnItemClickListener(OnItemClickListener l) {
this.onItemClickListener = l;
}
}
The Methods I think I have to change are AnimateGap and reorderChildren, but don't know how to do it exactly.
I'm a novice programmer, I'm make my first game in Java, and I just implemented a target AI, and now whenever I run it, always lags at start, I would like a explanation on why please or a way to do this better, Thank you in advance.
Code:(for what is most Likely causing the lag)
public class Handler {
//Use Linked Lists
private Animator a;
private boolean renderMini;
private int x, y;
public LinkedList<GameObject> object = new LinkedList<GameObject>();
public LinkedList<EntityObject> entity = new LinkedList<EntityObject>();
public LinkedList<Faction> faction = new LinkedList<Faction>();
public Handler(){
a = new Animator();
this.renderMini = false;
}
public void render(Graphics g){
///if(GameMain.numFrames > 5){
if(renderMini){
a.AnimateMini(g, x, y, 32, 32);
}
for(int i = 0; i < entity.size(); i++){
EntityObject tempObject = entity.get(i);
tempObject.render(g);
}
for(int i = 0; i < object.size(); i++){
GameObject tempObject = object.get(i);
tempObject.render(g);
}
//}
}
public void tick(){
//if(GameMain.numFrames > 5){
for(int i = 0; i < entity.size(); i++){
EntityObject tempObject = entity.get(i);
tempObject.tick();
}
for(int i = 0; i < object.size(); i++){
GameObject tempObject = object.get(i);
tempObject.tick();
}
for(int i = 0; i < faction.size(); i++){
Faction tempObject = faction.get(i);
tempObject.tick();
}
//}
}
public void addEntity(EntityObject o){
this.entity.add(o);
}
public void removeEntity(EntityObject o){
this.entity.remove(o);
}
public void addObject(GameObject o){
this.object.add(o);
}
public void removeObject(GameObject o){
if(o instanceof NpcLaser){
x = o.getX();
y = o.getY();
renderMini = true;
}
if(o instanceof PlayerLaser){
x = o.getX();
y = o.getY();
renderMini = true;
}
this.object.remove(o);
}
public void addFaction(Faction f){
this.faction.add(f);
}
public void removeFaction(Faction f){
this.faction.remove(f);
}
}
public class StandardShip extends EntityObject{
private Handler h;
private Random r;
private Animator a;
private Faction ef;
private EntityObject object;
private int desX, desY;
private int lx, ly, targetX, targetY; //target;
private boolean animateReady;
public static int isDead, ran, ra, rn;
public static boolean thisDeath;
public static boolean choAttack, choDefense, choSpeed, choShealth, choCommanding;
public StandardShip(int x, int y, int width, int height, Handler h, Faction f) {
super(x, y, width, height, h);
r = new Random();
a = new Animator();
this.setDeath(false);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.h = h;
/*this.isDead = 0;
this.thisDeath = false;
this.p = p;*/
this.health = 100;
this.animateReady = false;
//this.target = 1;
this.killLim = r.nextInt(4) + 1;
EntityObject.f = f;
EntityObject.f.addMember(this);
this.attackLim = 20;
this.defenseLim = 20;
this.speedLim = 20;
this.shealthLim = 20;
this.commandingLim = 20;
this.currency = 0;
this.attack = r.nextInt(attackLim);
this.defense = r.nextInt(defenseLim) + 1;
this.speed = r.nextInt(speedLim) + 2;
this.shealth = r.nextInt(shealthLim);
this.commanding = r.nextInt(commandingLim);
this.velX = 1;
this.velY = 1;
this.SearchTime = 1000;
this.desX = r.nextInt(Window.screensize.width + 1000);
this.desY = r.nextInt(Window.screensize.height + 1000);
//this.vectW = 5;
rn = r.nextInt(5);
if(rn == 0){
if(attack < 15){
attack = r.nextInt(attackLim) + 15;
}
}
if(rn == 1){
if(defense < 15){
defense = r.nextInt(defenseLim) + 15;
}
}
if(rn == 2){
if(speed < 15){
speed = r.nextInt(speedLim) + 15;
}
}
if(rn == 3){
if(shealth < 15){
shealth = r.nextInt(shealthLim) + 15;
}
}
if(rn == 4){
if(commanding < 15){
commanding = r.nextInt(commandingLim) + 15;
}
}
if(choAttack){
if(attack < 15){
attack = r.nextInt(attackLim) + 15;
}
}
if(choDefense){
if(defense < 15){
defense = r.nextInt(defenseLim) + 15;
}
}
if(choSpeed){
if(speed < 15){
speed = r.nextInt(speedLim) + 15;
}
}
if(choShealth){
if(shealth < 15){
shealth = r.nextInt(shealthLim) + 15;
}
}
if(choCommanding){
if(commanding < 15){
commanding = r.nextInt(commandingLim) + 15;
}
}
}
public void tick() {
x = GameMain.clamp(0, Window.screensize.width + 1000, x);
y = GameMain.clamp(0, Window.screensize.height + 1000, y);
x += velX;
y += velY;
EnemySize = f.isEnemy.size();
if(coolDown > 0){
coolDown--;
coolDown = GameMain.clamp(0, 1000, coolDown);
}
if(this.target == null){
for(int i = 0; i < EnemySize; i++){
ef = EntityObject.f.isEnemy.get(i);
memberSize = ef.members.size();
}
}
for(int i = 0; i < ef.members.size(); i++){
object = ef.members.get(i);
if(object.getX() >= this.x && object.getX() <= this.x + 300){
this.setTarget(object);
System.out.println("TargetSS");
i = ef.members.size();
}
if(object.getY() >= this.y && object.getY() <= this.y + 300){
this.setTarget(object);
System.out.println("TargetSS");
i = ef.members.size();
}
}
if(this.target != null && coolDown <= 0){
targetX = this.target.getX();
targetY = this.target.getY();
attack(targetX, targetY);
coolDown = 500;
}
if(this.target == null){
wander();
}
/*rand = r.nextInt(100);
if(kills == killLim){
level++;
levelUp();
kills = 0;
killLim += killLim/2;
}
x += velX;
y += velY;
if(y < vectY && velY == -1){velY *= -1;}
if(y > vectY && velY == 1){velY *= -1;}
if(x < vectX && velX == -1){velX *= -1;}
if(x > vectX && velX == 1){velX *= -1;}
if(x == vectX){
if(r.nextInt(2) == 0){
vectX = r.nextInt(Window.screensize.width);
}else{
velX = 0;
}
}
if(y == vectY){
if(r.nextInt(2) == 0){
vectY = r.nextInt(Window.screensize.height);
}else{
velY = 0;
}
}*/
if(this.isDamage > 0 && this.isDamage > defense){
health -= isDamage - (defense / 2);
isDamage = 0;
//System.out.println("HELLO");
}
}
public void wander(){
if(y < desY && velY == -1){velY *= -1;}
if(y > desY && velY == 1){velY *= -1;}
if(x < desX && velX == -1){velX *= -1;}
if(x > desX && velX == 1){velX *= -1;}
System.out.println("desY: "+desY+" desX: "
+desX+" Y: "+y+" X: "+x+" velX: "+velX+" velY: "+velY);
if(x == desX){
//if(r.nextInt(2) == 0){
desX = r.nextInt(Window.screensize.width + 1000);
//}else{
velX = 0;
//}
}
if(y == desY){
//if(r.nextInt(2) == 0){
desY = r.nextInt(Window.screensize.height + 1000);
//}else{
velY = 0;
//}
}
}
public void levelUp(){
this.health += r.nextInt(300) + 100;
this.attack += r.nextInt(attackLim);
this.defense += r.nextInt(defenseLim) + 1;
this.speed += r.nextInt(speedLim) + 2;
this.shealth += r.nextInt(shealthLim);
this.commanding += r.nextInt(commandingLim);
if(choAttack){
attack += (r.nextInt(attackLim) + 15)/2;
}
if(choDefense){
defense += (r.nextInt(defenseLim) + 15)/2;
}
if(choSpeed){
speed += (r.nextInt(speedLim) + 15)/2;
}
if(choShealth){
shealth += (r.nextInt(shealthLim) + 15)/2;
}
if(choCommanding){
commanding += (r.nextInt(commandingLim) + 15)/2;
}
}
public void Collision(Graphics g){
/*for(int i = 0; i < h.object.size(); i++){
GameObject tempObject = h.object.get(i);
if(tempObject.getId() == ID.Money){
Money m = (Money) tempObject;
if(getBounds().intersects(tempObject.getBounds())){
currency += m.getCashValue();
h.removeObject(tempObject);
}
}
if(tempObject.getId() == ID.ShipPart){
ShipPart s = (ShipPart) tempObject;
if(getBounds().intersects(tempObject.getBounds())){
numShipParts++;
h.removeObject(tempObject);
}
}
if(tempObject.getId() == ID.Meteor){
Meteor m = (Meteor) tempObject;
if(getBounds().intersects(tempObject.getBounds())){
Rectangle OverLap = getBounds().intersection(tempObject.getBounds());
if(OverLap.height >= OverLap.width){
if(m.isDoesDamage() && !m.isExplodes() && !m.isOnFire()){
this.health -= m.getDamage();
velX *= -2;
}
if(m.isDoesDamage() && m.isExplodes() || m.isDoesDamage() && m.isOnFire()){
if(m.isExplodes()){
a.AnimateExplosion(g, tempObject.getX(), tempObject.getY(), 32, 32);
this.health -= m.getDamage();
if(a.isFin[0]){
h.removeObject(tempObject);
a.isFin[0] = false;
}
}
if(m.isOnFire()){
this.health -= m.getDamage();
velX *= -2;
}
}else{
velX *= -2;
}
}
if(OverLap.width >= OverLap.height){
if(m.isDoesDamage() && !m.isExplodes() && !m.isOnFire()){
this.health -= m.getDamage();
velY *= -2;
}
if(m.isDoesDamage() && m.isExplodes() || m.isDoesDamage() && m.isOnFire()){
if(m.isExplodes()){
this.health -= m.getDamage();
m.setExplodeNow(true);
}
if(m.isOnFire()){
this.health -= m.getDamage();
velY *= -2;
}
}else{
velY *= -2;
}
}
}
}
if(tempObject.getId() == ID.Player){
p = (Player) tempObject;
if(getBounds().intersects(tempObject.getBounds())){
Rectangle OverLap = getBounds().intersection(tempObject.getBounds());
health -= r.nextInt(10) + 10;
p.setDamage(r.nextInt(10) + 10);
if(OverLap.height >= OverLap.width){
tempObject.setVelX(0);
}
if(OverLap.width >= OverLap.height){
tempObject.setVelY(0);
}
}
}
}*/
}
public void attack(int targetX, int targetY){
System.out.println("Hello");
h.addObject(new NpcLaser(x + 60, y + 60, 5, 9, h, f, targetX, targetY, this.attack));
}
public void render(Graphics g) {
a.AnimateEnemy(g, this.x, this.y, this.width, this.height, f);
if(animateReady){
a.AnimateMini(g, lx, ly, ran, ran);
}
if(health <= 0){
setDeath(true);
StandardShip.thisDeath = true;
a.AnimateExplosion(g, x, y, width, height);
if(Animator.isFin[0]){
ra = r.nextInt(10);
isDead++;
if(ra <= 7){
h.addObject(new Money(x, y, 32, 32, ID.Money, h, currency));
}else{
for(int i = 0; i < numShipParts; i++){
h.addObject(new ShipPart(x, y, 32, 32, ID.ShipPart, h));
}
}
h.removeEntity(this);
Animator.isFin[0] = false;
}
}
g.setColor(Color.red);
}
public Rectangle getBounds() {
return new Rectangle(x + 40, y + 37, 50, 50);
}
}
public class NpcLaser extends GameObject{
private Handler h;
private Faction f, ef;
private int laserAim;
private int currentTarget;
private int vectorX, vectorY;
private int damage;
public NpcLaser(int x, int y, int width, int height, Handler h, Faction f, int targetX, int targetY, int attack) {
super(x, y, width, height, h);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.h = h;
this.f = f;
this.vectorX = targetX;
this.vectorY = targetY;
this.damage = attack;
new Animator();
aimAI();
}
public void tick() {
System.out.println("Hello");
//Collision(g);
x += velX;
y += velY;
if(velX == 0 && velY == 0){
h.object.remove();
}
for(int i = 0; i < f.isEnemy.size(); i++){
ef = f.isEnemy.get(i);
}
for(int u = 0; u < ef.members.size(); u++){
EntityObject eo = ef.members.get(u);
if(getBounds().intersects(eo.getBounds())){
eo.setDamage(damage);
h.removeObject(this);
}
}
if(x > Window.screensize.getWidth() + 1200 || x < 0 - 1200){
h.removeObject(this);
}
if(y > Window.screensize.getHeight() + 1200 || y < 0 - 1200){
h.removeObject(this);
}
}
public void aimAI(){
if(x < vectorX){velX = 10;}
if(x > vectorX){velX = -10;}
if(y < vectorY){velY = 10;}
if(y > vectorY){velY = -10;}
if(x <= vectorX + 60 && x >= vectorX - 60){velX = 0;}
if(y <= vectorY + 60 && y >= vectorY - 60){velY = 0;}
}
public void render(Graphics g) {
/*if(p.isRemoveShot()){
h.removeObject(this);
p.setRemoveShot(false);
}*/
if(velX == 10 && velY == 10 || velX == -10 && velY == -10){
laserAim = 3;
}
if(velX == 10 && velY == -10 || velX == -10 && velY == 10){
laserAim = 2;
}
if(velX == 10 && velY == 0 || velX == -10 && velY == 0){
laserAim = 1;
}
if(velX == 0 && velY == 10 || velX == 0 && velY == -10){
laserAim = 0;
}
if(laserAim == 0){
g.drawImage(Assets.playerLaser, x, y, width, height, null);
}
if(laserAim == 1){
g.drawImage(Assets.playerLaser1, x, y, width, height, null);
}
if(laserAim == 2){
g.drawImage(Assets.playerLaser2, x, y, width, height, null);
}
if(laserAim == 3){
g.drawImage(Assets.playerLaser3, x, y, width, height, null);
}
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public int getCurrentTarget() {
return currentTarget;
}
public void setCurrentTarget(int currentTarget) {
this.currentTarget = currentTarget;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
}
Full Source Code Here
for(int i = 0; i < entity.size(); i++){
EntityObject tempObject = entity.get(i);
tempObject.render(g);
}
Your code includes several loops that look like this, and each take quadratic time, because they're running over LinkedList, which requires O(n) time for get. You should almost certainly be using an ArrayList, or at minimum, using a for-each loop, e.g.
for (EntityObject tempObject : entity) {
tempObject.render(g);
}
So I have code that runs, but I need to write the test for one of the classes (Cells) and I'm not sure how to go about this.
Typically, I'd have a helper class at the start of CellsTest, which would encapsulate the constructor call, which relies on the specific class name of the class that implements the overall program. This helper class would return an instance of that program.
So, what I'd think is that I'd need to have something like:
private Maze createMaze() {
return new Maze();
}
But then, my test methods can't access the Cell methods, just the Maze methods...So I'm guessing that that is wrong, and I'm not sure how I should actually be doing this.
//Maze.java
package falstad;
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Class handles the user interaction for the maze.
*/
//public class Maze extends Panel {
public class Maze {
final private ArrayList<Viewer> views = new ArrayList<Viewer>() ;
MazePanel panel ; // graphics to draw on, shared by all views
private int state;
private int percentdone = 0;
private boolean showMaze;
private boolean showSolution;
private boolean solving;
private boolean mapMode;
//static final int viewz = 50;
int viewx, viewy, angle;
int dx, dy;
int px, py ;
int walkStep;
int viewdx, viewdy;
boolean deepdebug = false;
boolean allVisible = false;
boolean newGame = false;
int mazew; // width
int mazeh; // height
Cells mazecells ;
Distance mazedists ;
Cells seencells ;
BSPNode rootnode ;
// Mazebuilder is used to calculate a new maze together with a solution
// The maze is computed in a separate thread. It is started in the local Build method.
MazeBuilder mazebuilder;
final int ESCAPE = 27;
int method = 0 ; // 0 : default method, Falstad's original code
int zscale = Constants.VIEW_HEIGHT/2;
private RangeSet rset;
//Constructor
public Maze() {
super() ;
panel = new MazePanel() ;
}
//selects a generation method
public Maze(int method)
{
super() ;
if (1 == method)
this.method = 1 ;
panel = new MazePanel() ;
}
public void init() {
state = Constants.STATE_TITLE;
rset = new RangeSet();
panel.initBufferImage() ;
addView(new MazeView(this)) ;
notifyViewerRedraw() ;
}
// Method obtains a new Mazebuilder and computes new maze
private void build(int skill) {
state = Constants.STATE_GENERATING;
percentdone = 0;
notifyViewerRedraw() ;
// select generation method
switch(method){
case 1 : mazebuilder = new MazeBuilderPrim();
break ;
case 0:
default : mazebuilder = new MazeBuilder();
break ;
}
mazew = Constants.SKILL_X[skill];
mazeh = Constants.SKILL_Y[skill];
mazebuilder.build(this, mazew, mazeh, Constants.SKILL_ROOMS[skill], Constants.SKILL_PARTCT[skill]);
}
//Call back method for MazeBuilder to communicate newly generated maze
public void newMaze(BSPNode root, Cells c, Distance dists, int startx, int starty) {
if (Cells.deepdebugWall)
{
c.saveLogFile(Cells.deepedebugWallFileName);
}
showMaze = showSolution = solving = false;
mazecells = c ;
mazedists = dists;
seencells = new Cells(mazew+1,mazeh+1) ;
rootnode = root ;
setCurrentDirection(1, 0) ;
setCurrentPosition(startx,starty) ;
walkStep = 0;
viewdx = dx<<16;
viewdy = dy<<16;
angle = 0;
mapMode = false;
state = Constants.STATE_PLAY;
cleanViews() ;
addView(new FirstPersonDrawer(Constants.VIEW_WIDTH,Constants.VIEW_HEIGHT,
Constants.MAP_UNIT,Constants.STEP_SIZE, mazecells, seencells, 10, mazedists.getDists(), mazew, mazeh, root, this)) ;
addView(new MapDrawer(Constants.VIEW_WIDTH,Constants.VIEW_HEIGHT,Constants.MAP_UNIT,Constants.STEP_SIZE, mazecells, seencells, 10, mazedists.getDists(), mazew, mazeh, this)) ;
notifyViewerRedraw() ;
}
public void addView(Viewer view) {
views.add(view) ;
}
public void removeView(Viewer view) {
views.remove(view) ;
}
private void cleanViews() {
Iterator<Viewer> it = views.iterator() ;
while (it.hasNext())
{
Viewer v = it.next() ;
if ((v instanceof FirstPersonDrawer)||(v instanceof MapDrawer))
{
//System.out.println("Removing " + v);
it.remove() ;
}
}
}
private void notifyViewerRedraw() {
Iterator<Viewer> it = views.iterator() ;
while (it.hasNext())
{
Viewer v = it.next() ;
v.redraw(panel.getBufferGraphics(), state, px, py, viewdx, viewdy, walkStep, Constants.VIEW_OFFSET, rset, angle) ;
}
panel.update() ;
}
private void notifyViewerIncrementMapScale() {
Iterator<Viewer> it = views.iterator() ;
while (it.hasNext())
{
Viewer v = it.next() ;
v.incrementMapScale() ;
}
panel.update() ;
}
private void notifyViewerDecrementMapScale() {
Iterator<Viewer> it = views.iterator() ;
while (it.hasNext())
{
Viewer v = it.next() ;
v.decrementMapScale() ;
}
panel.update() ;
}
boolean isInMapMode() {
return mapMode ;
}
boolean isInShowMazeMode() {
return showMaze ;
}
boolean isInShowSolutionMode() {
return showSolution ;
}
public String getPercentDone(){
return String.valueOf(percentdone) ;
}
public Panel getPanel() {
return panel ;
}
private void setCurrentPosition(int x, int y)
{
px = x ;
py = y ;
}
private void setCurrentDirection(int x, int y)
{
dx = x ;
dy = y ;
}
void buildInterrupted() {
state = Constants.STATE_TITLE;
notifyViewerRedraw() ;
mazebuilder = null;
}
final double radify(int x) {
return x*Math.PI/180;
}
public boolean increasePercentage(int pc) {
if (percentdone < pc && pc < 100) {
percentdone = pc;
if (state == Constants.STATE_GENERATING)
{
notifyViewerRedraw() ;
}
else
dbg("Warning: Receiving update request for increasePercentage while not in generating state, skip redraw.") ;
return true ;
}
return false ;
}
private void dbg(String str) {
//System.out.println(str);
}
private void logPosition() {
if (!deepdebug)
return;
dbg("x="+viewx/Constants.MAP_UNIT+" ("+
viewx+") y="+viewy/Constants.MAP_UNIT+" ("+viewy+") ang="+
angle+" dx="+dx+" dy="+dy+" "+viewdx+" "+viewdy);
}
private boolean checkMove(int dir) {
int a = angle/90;
if (dir == -1)
a = (a+2) & 3;
return mazecells.hasMaskedBitsFalse(px, py, Constants.MASKS[a]) ;
}
private void rotateStep() {
angle = (angle+1800) % 360;
viewdx = (int) (Math.cos(radify(angle))*(1<<16));
viewdy = (int) (Math.sin(radify(angle))*(1<<16));
moveStep();
}
private void moveStep() {
notifyViewerRedraw() ;
try {
Thread.currentThread().sleep(25);
} catch (Exception e) { }
}
private void rotateFinish() {
setCurrentDirection((int) Math.cos(radify(angle)), (int) Math.sin(radify(angle))) ;
logPosition();
}
private void walkFinish(int dir) {
setCurrentPosition(px + dir*dx, py + dir*dy) ;
if (isEndPosition(px,py)) {
state = Constants.STATE_FINISH;
notifyViewerRedraw() ;
}
walkStep = 0;
logPosition();
}
private boolean isEndPosition(int x, int y) {
return x < 0 || y < 0 || x >= mazew || y >= mazeh;
}
synchronized private void walk(int dir) {
if (!checkMove(dir))
return;
for (int step = 0; step != 4; step++) {
walkStep += dir;
moveStep();
}
walkFinish(dir);
}
synchronized private void rotate(int dir) {
final int originalAngle = angle;
final int steps = 4;
for (int i = 0; i != steps; i++) {
angle = originalAngle + dir*(90*(i+1))/steps;
rotateStep();
}
rotateFinish();
}
//CLASS CONTROLLING PLAYER MOVEMENTS, REMOVED FOR CHARACTER COUNT
}
}
//Cells.java
package falstad;
import java.io.BufferedWriter;
import java.io.FileWriter;
//This class encapsulates all access to a grid of cells
public class Cells {
private int width;
private int height ;
private int[][] cells;
public Cells(int w, int h) {
width = w ;
height = h ;
cells = new int[w][h];
}
public Cells(int[][] target){
this(target.length, target[0].length);
for (int i=0; i<width; i++)
for (int j=0; j<height; j++)
this.cells[i][j]=target[i][j];
}
public int getCells( int x, int y )
{
return cells[x][y] ;
}
static public int[] getMasks() {
return Constants.MASKS ;
}
public boolean canGo(int x, int y, int dx, int dy) {
if (hasMaskedBitsTrue(x, y, (getBit(dx, dy) << Constants.CW_BOUND_SHIFT)))
return false;
return isFirstVisit(x+dx, y+dy);
}
private int getBit(int dx, int dy) {
int bit = 0;
switch (dx + dy * 2) {
case 1: bit = Constants.CW_RIGHT; break;
case -1: bit = Constants.CW_LEFT; break;
case 2: bit = Constants.CW_BOT; break;
case -2: bit = Constants.CW_TOP; break;
default: dbg("getBit problem "+dx+" "+dy); break;
}
return bit;
}
//CLASSES FOR BITWISE ADJUSTMENTS, REMOVED FOR CHARACTER COUNT
public void initialize() {
int x, y;
for (x = 0; x != width; x++) {
for (y = 0; y != height; y++) {
setBitToOne(x, y, (Constants.CW_VISITED | Constants.CW_ALL));
}
setBitToOne(x, 0, Constants.CW_TOP_BOUND);
setBitToOne(x, height-1, Constants.CW_BOT_BOUND);
}
for (y = 0; y != height; y++) {
setBitToOne(0, y, Constants.CW_LEFT_BOUND);
setBitToOne(width-1, y, Constants.CW_RIGHT_BOUND);
}
}
public boolean areaOverlapsWithRoom(int rx, int ry, int rxl, int ryl) {
int x, y;
for (x = rx-1; x <= rxl+1; x++)
{
for (y = ry-1; y <= ryl+1; y++)
{
if (isInRoom(x, y))
return true ;
}
}
return false ;
}
private void deleteBound(int x, int y, int dx, int dy) {
setBoundToZero(x, y, dx, dy);
setBoundToZero(x+dx, y+dy, -dx, -dy) ;
}
public void addBoundWall(int x, int y, int dx, int dy) {
setBoundAndWallToOne(x, y, dx, dy);
setBoundAndWallToOne(x+dx, y+dy, -dx, -dy);
}
public void deleteWall(int x, int y, int dx, int dy) {
setWallToZero(x, y, dx, dy);
setWallToZero(x+dx, y+dy, -dx, -dy);
if (deepdebugWall)
logWall( x, y, dx, dy);
public void markAreaAsRoom(int rw, int rh, int rx, int ry, int rxl, int ryl) {
int x;
int y;
for (x = rx; x <= rxl; x++)
for (y = ry; y <= ryl; y++) {
setAllToZero(x, y);
setInRoomToOne(x, y);
}
for (x = rx; x <= rxl; x++) {
addBoundWall(x, ry, 0, -1);
addBoundWall(x, ryl, 0, 1);
}
for (y = ry; y <= ryl; y++) {
addBoundWall(rx, y, -1, 0);
addBoundWall(rxl, y, 1, 0);
}
int wallct = (rw+rh)*2;
SingleRandom random = SingleRandom.getRandom() ;
for (int ct = 0; ct != 5; ct++) {
int door = random.nextIntWithinInterval(0, wallct-1);
int dx, dy;
if (door < rw*2) {
y = (door < rw) ? 0 : rh-1;
dy = (door < rw) ? -1 : 1;
x = door % rw;
dx = 0;
} else {
door -= rw*2;
x = (door < rh) ? 0 : rw-1;
dx = (door < rh) ? -1 : 1;
y = door % rh;
dy = 0;
}
deleteBound(x+rx, y+ry, dx, dy);
}
}
public boolean hasMaskedBitsTrue(int x, int y, int bitmask) {
return (cells[x][y] & bitmask) != 0;
}
public boolean isInRoom(int x, int y) {
return hasMaskedBitsTrue(x, y, Constants.CW_IN_ROOM);
}
private boolean isFirstVisit(int x, int y) {
return hasMaskedBitsTrue(x, y, Constants.CW_VISITED);
}
public boolean hasWallOnRight(int x, int y) {
return hasMaskedBitsTrue(x, y, Constants.CW_RIGHT);
}
public boolean hasWallOnLeft(int x, int y) {
return hasMaskedBitsTrue(x, y, Constants.CW_LEFT);
}
public boolean hasWallOnTop(int x, int y) {
return hasMaskedBitsTrue(x, y, Constants.CW_TOP);
}
public boolean hasWallOnBottom(int x, int y) {
return hasMaskedBitsTrue(x, y, Constants.CW_BOT);
}
public boolean hasNoWallOnBottom(int x, int y) {
return !hasMaskedBitsTrue(x, y, Constants.CW_BOT);
}
public boolean hasNoWallOnTop(int x, int y) {
return !hasMaskedBitsTrue(x, y, Constants.CW_TOP);
}
public boolean hasNoWallOnLeft(int x, int y) {
return !hasMaskedBitsTrue(x, y, Constants.CW_LEFT);
}
public boolean hasNoWallOnRight(int x, int y) {
return !hasMaskedBitsTrue(x, y, Constants.CW_RIGHT);
}
public boolean hasMaskedBitsFalse(int x, int y, int bitmask) {
return (cells[x][y] & bitmask) == 0;
}
public boolean hasMaskedBitsGTZero(int x, int y, int bitmask) {
return (cells[x][y] & bitmask) > 0;
}
private void dbg(String str) {
System.out.println("Cells: "+str);
}
public String toString() {
String s = "" ;
for (int i = 0 ; i < width ; i++)
{
for (int j = 0 ; j < height ; j++)
s += " i:" + i + " j:" + j + "=" + cells[i][j] ;
s += "\n" ;
}
return s ;
}
static boolean deepdebugWall = false;
static final String deepedebugWallFileName = "logDeletedWalls.txt" ;
StringBuffer traceWall = (deepdebugWall) ? new StringBuffer("x y dx dy\n") : null ;
private void logWall(int x, int y, int dx, int dy) {
if (null != traceWall)
{
traceWall.append(x + " " + y + " " + dx + " " + dy + "\n");
}
}
public void saveLogFile( String filename )
{
try {
BufferedWriter out = new BufferedWriter(new FileWriter(filename));
out.write(traceWall.toString());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//MazeBuilder.java
package falstad;
public class MazeBuilder implements Runnable {
protected int width, height ;
Maze maze;
private int rooms;
int expectedPartiters;
protected int startx, starty ;
protected Cells cells;
protected Distance dists ;
protected SingleRandom random ;
Thread buildThread;
public MazeBuilder(){
random = SingleRandom.getRandom();
}
public MazeBuilder(boolean deterministic){
if (true == deterministic)
{
System.out.println("Project 2: functionality to make maze generation deterministic not implemented yet! Fix this!");
}
random = SingleRandom.getRandom();
}
static int getSign(int num) {
return (num < 0) ? -1 : (num > 0) ? 1 : 0;
}
protected void generate() {
generatePathways();
final int[] remote = dists.computeDistances(cells) ;
final int[] pos = dists.getStartPosition();
startx = pos[0] ;
starty = pos[1] ;
setExitPosition(remote[0], remote[1]);
}
protected void generatePathways() {
int[][] origdirs = new int[width][height] ;
int x = random.nextIntWithinInterval(0, width-1) ;
int y = 0;
final int firstx = x ;
final int firsty = y ;
int dir = 0;
int origdir = dir;
cells.setVisitedFlagToZero(x, y);
while (true) {
int dx = Constants.DIRS_X[dir];
int dy = Constants.DIRS_Y[dir];
if (!cells.canGo(x, y, dx, dy)) {
dir = (dir+1) & 3;
if (origdir == dir) {
if (x == firstx && y == firsty)
break;
int odr = origdirs[x][y];
dx = Constants.DIRS_X[odr];
dy = Constants.DIRS_Y[odr];
x -= dx;
y -= dy;
origdir = dir = random.nextIntWithinInterval(0, 3);
}
} else {
cells.deleteWall(x, y, dx, dy);
x += dx;
y += dy;
cells.setVisitedFlagToZero(x, y);
origdirs[x][y] = dir;
origdir = dir = random.nextIntWithinInterval(0, 3);
}
}
}
protected void setExitPosition(int remotex, int remotey) {
int bit = 0;
if (remotex == 0)
bit = Constants.CW_LEFT;
else if (remotex == width-1)
bit = Constants.CW_RIGHT;
else if (remotey == 0)
bit = Constants.CW_TOP;
else if (remotey == height-1)
bit = Constants.CW_BOT;
else
dbg("Generate 1");
cells.setBitToZero(remotex, remotey, bit);
//System.out.println("exit position set to zero: " + remotex + " " + remotey + " " + bit + ":" + cells.hasMaskedBitsFalse(remotex, remotey, bit)
// + ", Corner case: " + ((0 == remotex && 0 == remotey) || (0 == remotex && height-1 == remotey) || (width-1 == remotex && 0 == remotey) || (width-1 == remotex && height-1 == remotey)));
}
static final int MIN_ROOM_DIMENSION = 3 ;
static final int MAX_ROOM_DIMENSION = 8 ;
private boolean placeRoom() {
final int rw = random.nextIntWithinInterval(MIN_ROOM_DIMENSION, MAX_ROOM_DIMENSION);
if (rw >= width-4)
return false;
final int rh = random.nextIntWithinInterval(MIN_ROOM_DIMENSION, MAX_ROOM_DIMENSION);
if (rh >= height-4)
return false;
final int rx = random.nextIntWithinInterval(1, width-rw-1);
final int ry = random.nextIntWithinInterval(1, height-rh-1);
final int rxl = rx+rw-1;
final int ryl = ry+rh-1;
if (cells.areaOverlapsWithRoom(rx, ry, rxl, ryl))
return false ;
cells.markAreaAsRoom(rw, rh, rx, ry, rxl, ryl);
return true;
}
static void dbg(String str) {
System.out.println("MazeBuilder: "+str);
}
public void build(Maze mz, int w, int h, int roomct, int pc) {
init(mz, w, h, roomct, pc);
buildThread = new Thread(this);
buildThread.start();
}
private void init(Maze mz, int w, int h, int roomct, int pc) {
maze = mz;
width = w;
height = h;
rooms = roomct;
expectedPartiters = pc;
cells = new Cells(w,h) ;
dists = new Distance(w,h) ;
//colchange = random.nextIntWithinInterval(0, 255);
}
static final long SLEEP_INTERVAL = 100 ;
try {
cells.initialize();
// rooms into maze
generateRooms();
Thread.sleep(SLEEP_INTERVAL) ;
// pathways into the maze,
generate();
Thread.sleep(SLEEP_INTERVAL) ;
final int colchange = random.nextIntWithinInterval(0, 255);
final BSPBuilder b = new BSPBuilder(maze, dists, cells, width, height, colchange, expectedPartiters) ;
BSPNode root = b.generateBSPNodes();
Thread.sleep(SLEEP_INTERVAL) ;
// dbg("partiters = "+partiters);
maze.newMaze(root, cells, dists, startx, starty);
}
catch (InterruptedException ex) {
// dbg("Catching signal to stop") ;
}
}
static final int MAX_TRIES = 250 ;
private int generateRooms() {
int tries = 0 ;
int result = 0 ;
while (tries < MAX_TRIES && result <= rooms) {
if (placeRoom())
result++ ;
else
tries++ ;
}
return result ;
}
public void interrupt() {
buildThread.interrupt() ;
}
}
Obviously, I'm not asking for someone to write a test for me - not that any of you would, as this is fairly obviously a homework assignment - but I'd like some help getting started on this. So if anyone could clue me into the surely obvious trick that I'm missing, that would be wonderful!
A unit test for Cells class can look like the below:
While you unit test the Cells class you might not need the Maze or MazeBuilder, you only need an instance of Cells class and call its methods in order to check that they work correctly isolated from the rest of the application.
Also take a look at this: Unit testing in Java - what is it? as it provides a good reference.
import org.junit.Assert;
import org.junit.Test;
public class CellsTest {
#Test
void testHasWallOnRight() {
//setup
int[][] target = new int[][] { { 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } };
Cells a = new Cells(target);
//act
boolean result = a.hasWallOnRight(1,1);
//assert
Assert.assertFalse(result);
}
}
I have a Custom View which draws lines an saves them to an ArrayList. What I want to be able to do is check if a specified point is on a line inside the Arraylist and return the line. I have been able to do this when the line is straight by using if (l.startX == l.stopX && l.startY < l.stopY but this doesn't work if the line is on an angle. I would also like to do this with drawText and drawCircle. Is there some simple way of doing this that I have missed?
DrawView.java
class Line {
float startX, startY, stopX, stopY;
public Line(float startX, float startY, float stopX, float stopY) {
this.startX = startX;
this.startY = startY;
this.stopX = stopX;
this.stopY = stopY;
}
public Line(float startX, float startY) { // for convenience
this(startX, startY, startX, startY);
}
}
public class DrawView extends View {
Paint paint = new Paint();
ArrayList<Line> lines = new ArrayList<Line>();
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
for (Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
lines.add(new Line(event.getX(), event.getY()));
return true;
}
else if ((event.getAction() == MotionEvent.ACTION_MOVE ||
event.getAction() == MotionEvent.ACTION_UP) &&
lines.size() > 0) {
Line current = lines.get(lines.size() - 1);
current.stopX = event.getX();
current.stopY = event.getY();
Invalidate();
return true;
}
else {
return false;
}
}
}
I don't know if there is a canvas library for this but manually you can:
go through your list of lines
form equations for each line in let's say slope-intercept form y = mx + b
plugin in the event.X() and event.Y() into the above equation as x and y for each line
if the 2 sides are equal then your touch event is on that line
After many hours of trying I managed to come up with a an algorithm to check if a point is on a given line using a mixture of slope-intersect formula and if (x = startX && y > startY && y < stopY) Below is the code, it returns true if point is on line otherwise false, hopefully this can save someone time!
public boolean checkPosition(float x, float y, float sx, float sy, float ex, float ey) {
float mX = ex - sx;
float mY = ey - sy;
float smX = sx - ex;
float smY = sy - ey;
float pmX = mX;
float pmY = mY;
float psmX = smX;
float psmY = smY;
float yY = ey - y;
float xX = ex - x;
float sX = sx - x;
float sY = sy - y;
float m = mY / mX;
float b = sy - (m * sx);
if (mX < 0) {
pmX = mX * - 1;
}
if (mY < 0) {
pmY = mY * - 1;
}
if (smX < 0) {
psmX = smX * - 1;
}
if (smY < 0) {
psmY = smY * - 1;
}
if (yY < 0) {
yY = yY * - 1;
}
if (xX < 0) {
xX = xX * - 1;
}
if (sX < 0) {
sX = sX * - 1;
}
if (sY < 0) {
sY = sY * - 1;
}
if (sy == ey && y == sy) {
if (sx >= ex) {
if (x <= sx && x >= ex) return true;
else return false;
}
else if (ex >= sx) {
if (x <= ex && x >= sx) return true;
else return false;
}
else return false;
}
else if (sx == ex && x == sx) {
if (sy >= ey) {
if (y <= sy && y >= ey) return true;
else return false;
}
else if (ey >= sy) {
if (y <= ey && y >= sy) return true;
else return false;
}
else return false;
}
else if (xX <= pmX && sX <= psmX && yY <= pmY && sY <= psmY) {
if (y == (m * x) + b) return true;
else return false;
}
else return false;
}