package com.droidquest.items; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import javax.swing.ImageIcon; import javax.swing.JPanel; import com.droidquest.Room; import com.droidquest.Wire; import com.droidquest.devices.Device; import com.droidquest.levels.Level; import com.droidquest.materials.ChipTrash; public class Item implements Serializable, Cloneable { public transient static Level level; public transient Item carrying; // What this item is carrying. public transient Item carriedBy; // What is carrying this item. public transient Image currentIcon; // Current image of this item. public transient ImageIcon[] icons; // Array of images for this item public transient Room room; // Room this item is currently in public transient Color outline; // Null, White, Grey public transient int automove; // 0=normal movement, 1=Move to autoX,autoY, 2=Move in autoX,autoY public transient int autoX; // Destination of automovement public transient int autoY; // Destination of automovement public Room InternalRoom = null; // Room inside this item, if any. protected int repeating=0; // Keyboard repeat. public int charge =0; // Battery Charge of this item, if any. public boolean grabbable=true; // Can this item be picked up? public int x,y; // Position X,Y protected int orgX, orgY; // origin, within graphics protected int width, height; // width & height of object from origin public Rectangle leftPortal; public Rectangle rightPortal; public Rectangle upPortal; public Rectangle downPortal; public boolean editable=false; public Item() { x=0; y=0; } public Item(String filename, int X, int Y, Room r) { x=X; y=Y; room = r; grabbable = true; // icons = new Image[1]; // icons[0]=Toolkit.getDefaultToolkit().getImage(filename); icons = new ImageIcon[1]; icons[0]=new ImageIcon(filename); currentIcon = icons[0].getImage(); } public void writeRef(ObjectOutputStream s) throws IOException { s.writeInt(level.items.indexOf(carrying)); s.writeInt(level.items.indexOf(carriedBy)); s.writeInt(level.rooms.indexOf(room)); s.writeInt(level.rooms.indexOf(InternalRoom)); } public void readRef(ObjectInputStream s) throws IOException { carrying = level.FindItem(s.readInt()); carriedBy = level.FindItem(s.readInt()); room = level.FindRoom(s.readInt()); InternalRoom = level.FindRoom(s.readInt()); GenerateIcons(); } public Image getIcon() { return currentIcon; } public int getWidth() { return width; } public int getHeight() { return height; } public int getX() { return (x-orgX); } public int getY() { return (y-orgY); } public Room getRoom() { return room; } public void PicksUp(Item item) { // This picks up an item if (carrying == null) if (item.CanBePickedUp(this) == true && item.carriedBy == null) { carrying = item; item.carriedBy = this; item.x -= x; item.y -= y; item.outline=Color.white; level.PlaySound(room,Level.PICKUPSOUND); } } public void Drops() { // This drops the carried item if (carrying != null) { Item item = carrying; carrying.carriedBy = null; Dimension d = GetXY(); carrying.x += d.width; carrying.y += d.height; if (carrying.x<0) { carrying.x += 560; carrying.room = room.leftRoom; } if (carrying.y<0) { carrying.y += 384; carrying.room = room.upRoom; } if (carrying.x>559) { carrying.x -= 560; carrying.room = room.rightRoom; } if (carrying.y>383) { carrying.y -= 384; carrying.room = room.downRoom; } carrying = null; outline=new Color(128,128,128); item.IsDropped(); level.PlaySound(room, Level.DROPSOUND); } } public void IsDropped() { if (!editable) return; int bigXl = (x)/28; int bigXr = (x+width-1)/28; int bigYt = (y)/32; int bigYb = (y+height-1)/32; if (bigXr>19) bigXr=19; if (bigYb>11) bigYb=11; for (int a=bigYt; a<=bigYb; a++) for (int b=bigXl; b<=bigXr; b++) { if (room.MaterialArray[a][b] instanceof ChipTrash) { SetRoom(null); // Cheap way to remove the wires; level.items.removeElement(this); level.PlaySound(room,Level.DISCHARGESOUND); return; } } return; } public void SetRoom(Room r) { // Goes through recursively from Item to carried item to carried // item.... Puts all items in the same room. Room cr = r; if (r != room) if (isDevice()) { Device device = (Device) this; for (int a = 0; a=560) { cr=r.rightRoom; x-=560; } if (y>=384) { cr=r.downRoom; y-=384; } } room = cr; automove=0; if (carrying != null) carrying.SetRoom(cr); } public boolean KeyUp(KeyEvent e) { // Handles keybord input. // Return TRUE if repaint is needed (usually for movement) return false; } public boolean KeyDown(KeyEvent e) { // Handles keybord input. // Return TRUE if repaint is needed (usually for movement) return false; } public void MouseClick(MouseEvent e) { int button=0; if ((e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) button = 1; if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) button = 3; if (button==1) { if (e.getClickCount()==1) { autoX = e.getX() - width/2; autoY = e.getY() - height/2; autoX -= autoX%2; // Even numbered pixel only! autoY -= autoY%2; automove = 1; } else if (e.getClickCount()==2) { int dx = e.getX() - width/2 - x; int dy = e.getY() - height/2 - y; if (Math.abs(dx) > Math.abs(dy)) { autoY=0; autoX=28; if (dx<0) autoX=-28; automove=2; } else { autoX=0; autoY=32; if (dy<0) autoY=-32; automove=2; } } } if (button==3) { KeyEvent k = new KeyEvent(e.getComponent(), e.getID(), e.getWhen(), 0, KeyEvent.VK_SPACE,' '); KeyUp(k); } } public void MoveUp(int dist) { int bigXl = x/28; int bigXr = (x+getWidth()-1)/28; int bigY = (y-dist)/32; if ( (level.materialAt(bigXl,bigY,room).Passable(this) == false) || (level.materialAt(bigXr,bigY,room).Passable(this) == false) ) { automove=0; int newDist = y - (bigY+1)*32; y = (bigY+1)*32; ItemEffectsMaterials(); return; } y=y-dist; if (y<0) { if (room.getUpRoom(this) != null) { // change Rooms y=y+384; SetRoom(room.getUpRoom(this)); } else if (this==level.player && room.portalItem != null) { // Exit item, Player only Dimension d = room.portalItem.GetXY(); x = d.width + (room.portalItem.width - width)/2; y = d.height + (room.portalItem.height - height)/2; SetRoom(room.portalItem.room); MoveUp(dist); } else { // stop at top y+=384; automove=0; } } ItemEffectsMaterials(); } public void MoveDown(int dist) { int bigXl = x/28; int bigXr = (x+getWidth()-1)/28; int bigY = (y+getHeight()-1+dist)/32; if ( (level.materialAt(bigXl,bigY,room).Passable(this) == false) || (level.materialAt(bigXr,bigY,room).Passable(this) == false) ) { automove=0; int newDist = bigY*32 - getHeight() - y; y += newDist; ItemEffectsMaterials(); return; } y=y+dist; if (y>383) { if (room.getDownRoom(this) != null) { // change Rooms y=y-384; SetRoom(room.getDownRoom(this)); } else if (this==level.player && room.portalItem != null) { // Exit item, GameCursor only Dimension d = room.portalItem.GetXY(); x = d.width + (room.portalItem.width - width)/2; y = d.height + (room.portalItem.height - height)/2; SetRoom(room.portalItem.room); MoveDown(dist); } else { // stop at bottom y-=384; automove=0; } } ItemEffectsMaterials(); } public void MoveLeft(int dist) { int bigX = (x-dist)/28; int bigYt = y/32; int bigYb = (y+getHeight()-1)/32; if ( (level.materialAt(bigX,bigYt,room).Passable(this) == false) || (level.materialAt(bigX,bigYb,room).Passable(this) == false) ) { automove=0; int newDist = x - (bigX+1)*28 ; x = (bigX+1)*28; ItemEffectsMaterials(); return; } x=x-dist; if (x<0) { if (room.getLeftRoom(this) != null) { // change Rooms x=x+560; SetRoom(room.getLeftRoom(this)); } else if (this==level.player && room.portalItem != null) { // Exit item, GameCursor only Dimension d = room.portalItem.GetXY(); x = d.width + (room.portalItem.width - width)/2; y = d.height + (room.portalItem.height - height)/2; SetRoom(room.portalItem.room); MoveLeft(dist); } else { // stop at Left x+=560; automove=0; } } ItemEffectsMaterials(); } public void MoveRight(int dist) { int bigX = (x+getWidth()-1+dist)/28; int bigYt = y/32; int bigYb = (y+getHeight()-1)/32; // if (bigX<20 && bigYb<20 && bigYt>=0) if ( (level.materialAt(bigX,bigYt,room).Passable(this) == false) || (level.materialAt(bigX,bigYb,room).Passable(this) == false) ) { automove=0; int newDist = bigX*28 - getWidth()- x; x += newDist; ItemEffectsMaterials(); return; } x=x+dist; if (x>559) { if (room.getRightRoom(this) != null) { // change Rooms x=x-560; SetRoom(room.getRightRoom(this)); } else if (this==level.player && room.portalItem != null) { // Exit item, GameCursor only Dimension d = room.portalItem.GetXY(); x = d.width + (room.portalItem.width - width)/2; y = d.height + (room.portalItem.height - height)/2; SetRoom(room.portalItem.room); MoveRight(dist); } else { // stop at Right x-=560; automove=0; } } ItemEffectsMaterials(); } public void MoveUp(boolean nudge) { int dist = 32; if (nudge) dist = 2; MoveUp(dist); } public void MoveDown(boolean nudge) { int dist = 32; if (nudge) dist = 2; MoveDown(dist); } public void MoveLeft(boolean nudge) { int dist = 28; if (nudge) dist = 2; MoveLeft(dist); } public void MoveRight(boolean nudge) { int dist = 28; if (nudge) dist = 2; MoveRight(dist); } public void Animate() { if (automove==1 && room == null) automove=0; if (automove==1) { int dx = autoX - x; int dy = autoY - y; if (dx==0 && dy==0) automove=0; if (dx<-28) dx =-28; if (dx>28) dx=28; if (dy<-32) dy=-32; if (dy>32) dy=32; if (dx>0) MoveRight(dx); if (dx<0) MoveLeft(-dx); if (dy>0) MoveDown(dy); if (dy<0) MoveUp(-dy); } if (automove==2) { if (autoX>0) MoveRight(autoX); if (autoX<0) MoveLeft(-autoX); if (autoY>0) MoveDown(autoY); if (autoY<0) MoveUp(-autoY); } } public void Decorate() { } public void GenerateIcons() { // This is where the icons[] array is filled with ImageIcons, and // the ImageIcons are painted. Depending on the Item, this can be // done either once during initialization, or once per Animation // phase. } public boolean CanBePickedUp(Item i) { // Returns True if THIS Item can be picked up by Item i. return grabbable; } private void ItemEffectsMaterials() { // called after every Move() function // // Checks the materials touched by this item, and calls their // Material.TouchedByItem(Item) if (room == null) return; Dimension d = GetXY(); int bigXl = (d.width)/28; int bigXr = (d.width+width-1)/28; int bigYt = (d.height)/32; int bigYb = (d.height+height-1)/32; if (bigXr>19) bigXr=19; if (bigYb>11) bigYb=11; for (int a=bigYt; a<=bigYb; a++) for (int b=bigXl; b<=bigXr; b++) if (a>=0 && a<12 && b>=0 &&b<20) room.MaterialArray[a][b].TouchedByItem(this); if (carrying != null) carrying.ItemEffectsMaterials(); } public Dimension GetXY() { // Recursively goes up the carrying tree to figure out the XY // coordinates of an item. if (carriedBy != null) { Dimension d = carriedBy.GetXY(); d.width += x; d.height += y; return d; } else return new Dimension(x,y); } public void Draw(Graphics g, JPanel jp) { Dimension d = GetXY(); if (currentIcon != null) g.drawImage(currentIcon, d.width-orgX, d.height-orgY, jp); else System.out.println("Cannot draw " + getClass()); if (outline != null) { g.setColor(outline); g.drawRect(d.width,d.height, width+1, height+1); g.drawRect(d.width+1,d.height+1, width-1, height-1); outline=null; } } public void Draw(Graphics g, int X, int Y, JPanel jp) { g.drawImage(currentIcon, X - orgX, Y - orgY, jp); } public boolean Overlaps(Item testItem) { boolean overlap = false; if (this!=testItem && this.room == testItem.room) { overlap = true; Dimension d1 = GetXY(); Dimension d2 = testItem.GetXY(); if (this.carrying == testItem) {overlap=false;} if (this == testItem.carrying) {overlap=false;} if (d1.width + this.width < d2.width) {overlap=false;} if (d2.width + testItem.width < d1.width) {overlap=false;} if (d1.height + this.height < d2.height) {overlap=false;} if (d2.height + testItem.height < d1.height) {overlap=false;} } return overlap; } public boolean RightEnterOverlap(Item item) { boolean result = true; if (leftPortal!= null) { if (item.x < x + leftPortal.x) result = false; if (item.x > x + leftPortal.x + leftPortal.width) result = false; if (item.y < y + leftPortal.y) result = false; if (item.y > y + leftPortal.y + leftPortal.height) result = false; } else result = false; if (OverWall()) result=false; return result; } public boolean DownEnterOverlap(Item item) { boolean result = true; if (upPortal!=null) { if (item.x < x + upPortal.x) result = false; if (item.x > x + upPortal.x + upPortal.width) result = false; if (item.y < y + upPortal.y) result = false; if (item.y > y + upPortal.y + upPortal.height) result = false; } else result = false; if (OverWall()) result=false; return result; } public boolean LeftEnterOverlap(Item item) { boolean result = true; if (leftPortal!=null) { if (item.x < x + rightPortal.x) result = false; if (item.x > x + rightPortal.x + rightPortal.width) result = false; if (item.y < y + rightPortal.y) result = false; if (item.y > y + rightPortal.y + rightPortal.height) result = false; } else result = false; if (OverWall()) result=false; return result; } public boolean UpEnterOverlap(Item item) { boolean result = true; if (downPortal!=null) { if (item.x < x + downPortal.x) result = false; if (item.x > x + downPortal.x + downPortal.width) result = false; if (item.y < y + downPortal.y) result = false; if (item.y > y + downPortal.y + downPortal.height) result = false; } else result = false; if (OverWall()) result=false; return result; } public boolean isDevice() { return false; } public Object clone() { Object newObject = null; try { newObject = super.clone(); } catch (CloneNotSupportedException e) {} // if (newObject instanceof Device) // { // Device newDevice = (Device) newObject; // newDevice.ports = null; // newDevice.GenerateIcons(); // } return newObject; } public void Erase() { carrying = null; carriedBy = null; room = null; currentIcon=null; icons = null; InternalRoom = null; } public boolean OverWall() { Dimension d = GetXY(); int bigXL = (d.width+width/2-14)/28; int bigXR = (d.width+width/2+14)/28; int bigYT = (d.height+height/2-16)/32; int bigYB = (d.height+height/2+16)/32; if (bigXR>19) bigXR=19; if (bigYB>11) bigYB=11; boolean flag = false; for (int Y=bigYT; Y<=bigYB; Y++) for (int X=bigXL; X<=bigXR; X++) if (!room.MaterialArray[Y][X].passable) flag=true; return flag; } }