Code Sketch
yoiiiii
Category: Programming
import java.awt.BasicStroke
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Cursor
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.Font
import java.awt.GradientPaint
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.Point
import java.awt.RenderingHints
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseMotionAdapter
import javax.swing.DefaultListModel
import javax.swing.JButton
import javax.swing.JColorChooser
import javax.swing.JFileChooser
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JList
import javax.swing.JOptionPane
import javax.swing.JPanel
import javax.swing.JScrollPane
import javax.swing.JSplitPane
import javax.swing.JTabbedPane
import javax.swing.JTextArea
import javax.swing.JTextField
import javax.swing.ListSelectionModel
import javax.swing.SwingUtilities
import javax.swing.Timer
import javax.swing.WindowConstants
import scala.collection.mutable.ArrayBuffer
// ============================================================
// ULTRA LEGEND DRAW + GAME STUDIO X8
// ============================================================
val CANVAS_WIDTH = 1000
val CANVAS_HEIGHT = 650
val CENTER_X = 500
val CENTER_Y = 325
// ============================================================
// DRAW ITEM
// ============================================================
case class DrawItem(
points: Vector[Point],
strokeColor: Color,
fillColor: Color,
filled: Boolean,
itemName: String,
visible: Boolean,
locked: Boolean
)
// ============================================================
// GAME PADDLE LINE
// ============================================================
case class PaddleLine(
p1: Point,
p2: Point
)
// ============================================================
// DRAW STATE
// ============================================================
var drawItems =
ArrayBuffer[DrawItem]()
var undoStack =
ArrayBuffer[ArrayBuffer[DrawItem]]()
var redoStack =
ArrayBuffer[ArrayBuffer[DrawItem]]()
var currentTool =
"PENCIL"
var currentStrokeColor =
new Color(20, 90, 220)
var currentFillColor =
new Color(255, 180, 40)
var brushWidth =
5.0f
var gridEnabled =
true
var snapEnabled =
false
var drawingActive =
false
var selectedItemIndex =
-1
var movingSelected =
false
var resizingSelected =
false
var resizeMode =
""
var previousMousePoint =
new Point(0, 0)
var originalSelectedPoints =
Vector[Point]()
var temporaryPoints =
ArrayBuffer[Point]()
var generatedDrawingCode =
""
var generatedGameCode =
""
// ============================================================
// UI REFERENCES
// ============================================================
var mainFrame: JFrame =
null
var drawingCanvas: JPanel =
null
var drawingCodeArea: JTextArea =
null
var mainStatus: JLabel =
null
var objectModel =
new DefaultListModel[String]()
var shapeModel =
new DefaultListModel[String]()
var objectList: JList[String] =
null
var shapeList: JList[String] =
null
var objectSearchField: JTextField =
null
// ============================================================
// BUTTON HELPER
// ============================================================
def createButton(
label: String
): JButton = {
val b =
new JButton(label)
b.setFocusable(false)
b.setFont(
new Font(
"Arial",
Font.BOLD,
11
)
)
b
}
// ============================================================
// STATUS
// ============================================================
def setMainStatus(
message: String
): Unit = {
if (
mainStatus != null
) {
mainStatus.setText(
message
)
}
}
def repaintDrawingCanvas(): Unit = {
if (
drawingCanvas != null
) {
drawingCanvas.repaint()
}
}
// ============================================================
// HISTORY COPY
// ============================================================
def copyDrawItems(
source: ArrayBuffer[DrawItem]
): ArrayBuffer[DrawItem] = {
val result =
ArrayBuffer[DrawItem]()
var i =
0
while (
i < source.length
) {
val oldItem =
source(i)
val copiedPoints =
oldItem.points.map(
p =>
new Point(
p.x,
p.y
)
)
result +=
oldItem.copy(
points =
copiedPoints
)
i += 1
}
result
}
// ============================================================
// HISTORY
// ============================================================
def saveHistory(): Unit = {
undoStack +=
copyDrawItems(
drawItems
)
redoStack.clear()
while (
undoStack.length > 40
) {
undoStack.remove(0)
}
}
def performUndo(): Unit = {
if (
undoStack.nonEmpty
) {
redoStack +=
copyDrawItems(
drawItems
)
val previous =
undoStack.last
undoStack.remove(
undoStack.length - 1
)
drawItems.clear()
drawItems ++=
copyDrawItems(
previous
)
selectedItemIndex =
-1
repaintDrawingCanvas()
setMainStatus(
"UNDO COMPLETE"
)
} else {
setMainStatus(
"NOTHING TO UNDO"
)
}
}
def performRedo(): Unit = {
if (
redoStack.nonEmpty
) {
undoStack +=
copyDrawItems(
drawItems
)
val next =
redoStack.last
redoStack.remove(
redoStack.length - 1
)
drawItems.clear()
drawItems ++=
copyDrawItems(
next
)
selectedItemIndex =
-1
repaintDrawingCanvas()
setMainStatus(
"REDO COMPLETE"
)
} else {
setMainStatus(
"NOTHING TO REDO"
)
}
}
// ============================================================
// MOUSE GEOMETRY
// ============================================================
def snapCoordinate(
value: Int
): Int = {
if (
snapEnabled
) {
(value / 10) * 10
} else {
value
}
}
def canvasPoint(
e: MouseEvent
): Point = {
val px =
math.max(
0,
math.min(
CANVAS_WIDTH - 1,
snapCoordinate(
e.getX
)
)
)
val py =
math.max(
0,
math.min(
CANVAS_HEIGHT - 1,
snapCoordinate(
e.getY
)
)
)
new Point(
px,
py
)
}
def pointDistance(
a: Point,
b: Point
): Double = {
math.hypot(
b.x - a.x,
b.y - a.y
)
}
def isClosedShape(
points: Iterable[Point]
): Boolean = {
val seq =
points.toSeq
seq.length >= 3 &&
pointDistance(
seq.head,
seq.last
) <= 50
}
// ============================================================
// ITEM BOUNDS
// ============================================================
def itemBounds(
item: DrawItem
): java.awt.Rectangle = {
if (
item.points.isEmpty
) {
new java.awt.Rectangle(
0,
0,
1,
1
)
} else {
var minX =
item.points.head.x
var maxX =
item.points.head.x
var minY =
item.points.head.y
var maxY =
item.points.head.y
var i =
1
while (
i < item.points.length
) {
val p =
item.points(i)
if (
p.x < minX
) minX = p.x
if (
p.x > maxX
) maxX = p.x
if (
p.y < minY
) minY = p.y
if (
p.y > maxY
) maxY = p.y
i += 1
}
new java.awt.Rectangle(
minX,
minY,
math.max(
1,
maxX - minX
),
math.max(
1,
maxY - minY
)
)
}
}
// ============================================================
// SEGMENT DISTANCE
// ============================================================
def pointToSegmentDistance(
p: Point,
a: Point,
b: Point
): Double = {
val dx =
b.x - a.x
val dy =
b.y - a.y
if (
dx == 0 &&
dy == 0
) {
pointDistance(
p,
a
)
} else {
val numerator =
(
(p.x - a.x) * dx +
(p.y - a.y) * dy
).toDouble
val denominator =
(
dx * dx +
dy * dy
).toDouble
val t =
math.max(
0.0,
math.min(
1.0,
numerator /
denominator
)
)
val cx =
a.x +
t * dx
val cy =
a.y +
t * dy
math.hypot(
p.x - cx,
p.y - cy
)
}
}
// ============================================================
// POINT IN POLYGON
// ============================================================
def pointInsidePolygon(
p: Point,
points: Seq[Point]
): Boolean = {
if (
points.length < 3
) {
false
} else {
var inside =
false
var j =
points.length - 1
var i =
0
while (
i < points.length
) {
val xi =
points(i).x
val yi =
points(i).y
val xj =
points(j).x
val yj =
points(j).y
val hit =
(
(yi > p.y) !=
(yj > p.y)
) &&
(
p.x <
(
xj - xi
).toDouble *
(
p.y - yi
).toDouble /
(
yj - yi +
0.000001
) +
xi
)
if (
hit
) {
inside =
!inside
}
j =
i
i += 1
}
inside
}
}
// ============================================================
// HIT TEST
// ============================================================
def findItemAt(
p: Point
): Int = {
var found =
-1
var i =
drawItems.length - 1
while (
i >= 0 &&
found < 0
) {
val item =
drawItems(i)
if (
item.visible
) {
val b =
itemBounds(item)
val expanded =
new java.awt.Rectangle(
b.x - 15,
b.y - 15,
b.width + 30,
b.height + 30
)
if (
expanded.contains(p)
) {
if (
item.filled &&
isClosedShape(
item.points
) &&
pointInsidePolygon(
p,
item.points
)
) {
found =
i
} else {
var j =
1
while (
j < item.points.length &&
found < 0
) {
if (
pointToSegmentDistance(
p,
item.points(j - 1),
item.points(j)
) < 18
) {
found =
i
}
j += 1
}
}
}
}
i -= 1
}
found
}
// ============================================================
// RESIZE HANDLES
// ============================================================
def selectionHandles(
r: java.awt.Rectangle
): Array[(String, Point)] = {
val mx =
r.x +
r.width / 2
val my =
r.y +
r.height / 2
Array(
("TL", new Point(r.x, r.y)),
("TM", new Point(mx, r.y)),
("TR", new Point(r.x + r.width, r.y)),
("ML", new Point(r.x, my)),
("MR", new Point(r.x + r.width, my)),
("BL", new Point(r.x, r.y + r.height)),
("BM", new Point(mx, r.y + r.height)),
("BR", new Point(r.x + r.width, r.y + r.height))
)
}
def findResizeHandle(
item: DrawItem,
p: Point
): String = {
val b =
itemBounds(item)
val r =
new java.awt.Rectangle(
b.x - 8,
b.y - 8,
b.width + 16,
b.height + 16
)
val hs =
selectionHandles(r)
var answer =
""
var i =
0
while (
i < hs.length &&
answer == ""
) {
if (
pointDistance(
p,
hs(i)._2
) <= 14
) {
answer =
hs(i)._1
}
i += 1
}
answer
}
// ============================================================
// MOVE
// ============================================================
def moveSelectedItem(
dx: Int,
dy: Int
): Unit = {
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length
) {
val oldItem =
drawItems(
selectedItemIndex
)
if (
!oldItem.locked
) {
val movedPoints =
oldItem.points.map(
p =>
new Point(
p.x + dx,
p.y + dy
)
)
drawItems(
selectedItemIndex
) =
oldItem.copy(
points =
movedPoints
)
}
}
}
// ============================================================
// RESIZE
// ============================================================
def resizeSelectedItem(
p: Point
): Unit = {
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length &&
originalSelectedPoints.nonEmpty
) {
val oldItem =
drawItems(
selectedItemIndex
)
var minX =
originalSelectedPoints.head.x
var maxX =
originalSelectedPoints.head.x
var minY =
originalSelectedPoints.head.y
var maxY =
originalSelectedPoints.head.y
var i =
1
while (
i < originalSelectedPoints.length
) {
val q =
originalSelectedPoints(i)
if (
q.x < minX
) minX = q.x
if (
q.x > maxX
) maxX = q.x
if (
q.y < minY
) minY = q.y
if (
q.y > maxY
) maxY = q.y
i += 1
}
val oldWidth =
math.max(
1,
maxX - minX
)
val oldHeight =
math.max(
1,
maxY - minY
)
var newMinX =
minX
var newMaxX =
maxX
var newMinY =
minY
var newMaxY =
maxY
if (
resizeMode == "TL"
) {
newMinX =
p.x
newMinY =
p.y
} else if (
resizeMode == "TR"
) {
newMaxX =
p.x
newMinY =
p.y
} else if (
resizeMode == "BL"
) {
newMinX =
p.x
newMaxY =
p.y
} else if (
resizeMode == "BR"
) {
newMaxX =
p.x
newMaxY =
p.y
} else if (
resizeMode == "TM"
) {
newMinY =
p.y
} else if (
resizeMode == "BM"
) {
newMaxY =
p.y
} else if (
resizeMode == "ML"
) {
newMinX =
p.x
} else if (
resizeMode == "MR"
) {
newMaxX =
p.x
}
val newWidth =
math.max(
5,
newMaxX - newMinX
)
val newHeight =
math.max(
5,
newMaxY - newMinY
)
val scaled =
originalSelectedPoints.map(
q => {
val nx =
newMinX +
(
(
q.x - minX
).toDouble *
newWidth /
oldWidth
).toInt
val ny =
newMinY +
(
(
q.y - minY
).toDouble *
newHeight /
oldHeight
).toInt
new Point(
nx,
ny
)
}
)
drawItems(
selectedItemIndex
) =
oldItem.copy(
points =
scaled
)
}
}
// ============================================================
// SHAPE HELPERS
// ============================================================
def polygonPoints(
sideCount: Int,
radius: Int,
startAngle: Double
): Vector[Point] = {
val result =
ArrayBuffer[Point]()
var i =
0
while (
i <= sideCount
) {
val angle =
startAngle +
i *
2.0 *
math.Pi /
sideCount
result +=
new Point(
CENTER_X +
(
math.cos(angle) *
radius
).toInt,
CENTER_Y +
(
math.sin(angle) *
radius
).toInt
)
i += 1
}
result.toVector
}
def ellipsePoints(
radiusX: Int,
radiusY: Int
): Vector[Point] = {
val result =
ArrayBuffer[Point]()
var degree =
0
while (
degree <= 360
) {
val angle =
degree *
math.Pi /
180.0
result +=
new Point(
CENTER_X +
(
math.cos(angle) *
radiusX
).toInt,
CENTER_Y +
(
math.sin(angle) *
radiusY
).toInt
)
degree +=
3
}
result.toVector
}
def starPoints(
pointCount: Int,
outerRadius: Int
): Vector[Point] = {
val result =
ArrayBuffer[Point]()
var i =
0
while (
i <= pointCount * 2
) {
val angle =
-math.Pi / 2.0 +
i *
math.Pi /
pointCount
val radius =
if (
i % 2 == 0
) {
outerRadius
} else {
(
outerRadius *
0.45
).toInt
}
result +=
new Point(
CENTER_X +
(
math.cos(angle) *
radius
).toInt,
CENTER_Y +
(
math.sin(angle) *
radius
).toInt
)
i += 1
}
result.toVector
}
def heartPoints(): Vector[Point] = {
val result =
ArrayBuffer[Point]()
var i =
0
while (
i <= 180
) {
val t =
i *
math.Pi /
180.0
val x =
16 *
math.pow(
math.sin(t),
3
)
val y =
13 *
math.cos(t) -
5 *
math.cos(
2 * t
) -
2 *
math.cos(
3 * t
) -
math.cos(
4 * t
)
result +=
new Point(
CENTER_X +
(
x * 13
).toInt,
CENTER_Y -
(
y * 13
).toInt
)
i += 1
}
result.toVector
}
// ============================================================
// SHAPE LIBRARY
// ============================================================
val allShapeNames =
Array(
"LINE",
"SQUARE",
"RECTANGLE",
"CIRCLE",
"ELLIPSE",
"TRIANGLE",
"DIAMOND",
"PENTAGON",
"HEXAGON",
"HEPTAGON",
"OCTAGON",
"STAR 5",
"STAR 6",
"STAR 8",
"HEART",
"ARROW RIGHT",
"ARROW LEFT",
"ARROW UP",
"ARROW DOWN",
"PLUS",
"CLOUD",
"SUN",
"MOON",
"RING",
"ARC",
"WAVE",
"SPIRAL",
"BURST",
"SNOWFLAKE",
"SMILEY"
)
var shapeIndex =
0
while (
shapeIndex < allShapeNames.length
) {
shapeModel.addElement(
allShapeNames(shapeIndex)
)
shapeIndex += 1
}
// ============================================================
// SHAPE GEOMETRY
// ============================================================
def getShapeGeometry(
name: String
): Vector[Point] = {
val upper =
name.toUpperCase
if (
upper == "LINE"
) {
Vector(
new Point(100,150),
new Point(900,500)
)
} else if (
upper == "SQUARE"
) {
Vector(
new Point(300,125),
new Point(700,125),
new Point(700,525),
new Point(300,525),
new Point(300,125)
)
} else if (
upper == "RECTANGLE"
) {
Vector(
new Point(150,200),
new Point(850,200),
new Point(850,450),
new Point(150,450),
new Point(150,200)
)
} else if (
upper == "CIRCLE"
) {
ellipsePoints(
220,
220
)
} else if (
upper == "ELLIPSE"
) {
ellipsePoints(
300,
160
)
} else if (
upper == "TRIANGLE"
) {
polygonPoints(
3,
250,
-math.Pi / 2
)
} else if (
upper == "DIAMOND"
) {
Vector(
new Point(CENTER_X,75),
new Point(840,CENTER_Y),
new Point(CENTER_X,575),
new Point(160,CENTER_Y),
new Point(CENTER_X,75)
)
} else if (
upper == "PENTAGON"
) {
polygonPoints(
5,
250,
-math.Pi / 2
)
} else if (
upper == "HEXAGON"
) {
polygonPoints(
6,
240,
0
)
} else if (
upper == "HEPTAGON"
) {
polygonPoints(
7,
235,
-math.Pi / 2
)
} else if (
upper == "OCTAGON"
) {
polygonPoints(
8,
235,
math.Pi / 8
)
} else if (
upper == "STAR 5"
) {
starPoints(
5,
255
)
} else if (
upper == "STAR 6"
) {
starPoints(
6,
250
)
} else if (
upper == "STAR 8"
) {
starPoints(
8,
245
)
} else if (
upper == "HEART"
) {
heartPoints()
} else if (
upper == "ARROW RIGHT"
) {
Vector(
new Point(130,240),
new Point(620,240),
new Point(620,140),
new Point(860,325),
new Point(620,510),
new Point(620,410),
new Point(130,410),
new Point(130,240)
)
} else if (
upper == "ARROW LEFT"
) {
Vector(
new Point(870,240),
new Point(380,240),
new Point(380,140),
new Point(140,325),
new Point(380,510),
new Point(380,410),
new Point(870,410),
new Point(870,240)
)
} else if (
upper == "ARROW UP"
) {
Vector(
new Point(430,535),
new Point(430,300),
new Point(275,300),
new Point(500,70),
new Point(725,300),
new Point(570,300),
new Point(570,535),
new Point(430,535)
)
} else if (
upper == "ARROW DOWN"
) {
Vector(
new Point(430,115),
new Point(430,350),
new Point(275,350),
new Point(500,580),
new Point(725,350),
new Point(570,350),
new Point(570,115),
new Point(430,115)
)
} else if (
upper == "PLUS"
) {
Vector(
new Point(430,100),
new Point(570,100),
new Point(570,245),
new Point(715,245),
new Point(715,405),
new Point(570,405),
new Point(570,550),
new Point(430,550),
new Point(430,405),
new Point(285,405),
new Point(285,245),
new Point(430,245),
new Point(430,100)
)
} else if (
upper == "CLOUD"
) {
Vector(
new Point(170,470),
new Point(215,350),
new Point(330,270),
new Point(440,300),
new Point(530,195),
new Point(660,220),
new Point(770,320),
new Point(835,375),
new Point(800,470),
new Point(170,470)
)
} else if (
upper == "SUN"
) {
starPoints(
16,
250
)
} else if (
upper == "MOON"
) {
ellipsePoints(
230,
230
)
} else if (
upper == "RING"
) {
ellipsePoints(
230,
230
)
} else if (
upper == "ARC"
) {
val result =
ArrayBuffer[Point]()
var d =
-120
while (
d <= 120
) {
val a =
d *
math.Pi /
180.0
result +=
new Point(
CENTER_X +
(
math.cos(a) *
280
).toInt,
CENTER_Y +
(
math.sin(a) *
190
).toInt
)
d +=
3
}
result.toVector
} else if (
upper == "WAVE"
) {
val result =
ArrayBuffer[Point]()
var x =
40
while (
x <= 960
) {
result +=
new Point(
x,
CENTER_Y +
(
math.sin(
(x - 40) *
0.04
) *
105
).toInt
)
x +=
5
}
result.toVector
} else if (
upper == "SPIRAL"
) {
val result =
ArrayBuffer[Point]()
var angle =
0.0
var radius =
5.0
while (
angle < math.Pi * 8.0
) {
result +=
new Point(
CENTER_X +
(
math.cos(angle) *
radius
).toInt,
CENTER_Y +
(
math.sin(angle) *
radius
).toInt
)
angle +=
0.08
radius +=
1.6
}
result.toVector
} else if (
upper == "BURST"
) {
starPoints(
20,
255
)
} else if (
upper == "SNOWFLAKE"
) {
Vector(
new Point(CENTER_X,75),
new Point(CENTER_X,575),
new Point(245,160),
new Point(755,490),
new Point(245,490),
new Point(755,160)
)
} else {
ellipsePoints(
230,
160
)
}
}
// ============================================================
// OBJECT LIBRARY
// ============================================================
val allObjectNames =
Array(
"CAR",
"SPORTS CAR",
"RACING CAR",
"TRUCK",
"BUS",
"TRAIN",
"AIRPLANE",
"JET",
"HELICOPTER",
"ROCKET",
"BICYCLE",
"MOTORBIKE",
"SCOOTER",
"BOAT",
"SHIP",
"SUBMARINE",
"DRONE",
"UFO",
"HOUSE",
"VILLA",
"PALACE",
"CASTLE",
"TOWER",
"SCHOOL",
"HOSPITAL",
"BRIDGE",
"LIGHTHOUSE",
"CITY",
"SKYSCRAPER",
"STADIUM",
"TREE",
"PALM TREE",
"FLOWER",
"CACTUS",
"MUSHROOM",
"MOUNTAIN",
"VOLCANO",
"ISLAND",
"CLOUD",
"RAINBOW",
"SUN",
"MOON",
"PLANET",
"EARTH",
"SATURN",
"BOY",
"GIRL",
"MAN",
"WOMAN",
"PERSON",
"ROBOT",
"AI ROBOT",
"ASTRONAUT",
"KING",
"QUEEN",
"CAT",
"DOG",
"BIRD",
"FISH",
"SHARK",
"WHALE",
"DOLPHIN",
"LION",
"TIGER",
"ELEPHANT",
"HORSE",
"RABBIT",
"BEAR",
"PANDA",
"MONKEY",
"FOX",
"DEER",
"COW",
"GOAT",
"CHICKEN",
"DUCK",
"BUTTERFLY",
"BEE",
"SNAKE",
"TURTLE",
"APPLE",
"BANANA",
"ORANGE",
"MANGO",
"WATERMELON",
"PIZZA",
"BURGER",
"CAKE",
"ICE CREAM",
"GUITAR",
"PIANO",
"DRUM",
"CAMERA",
"COMPUTER",
"PHONE",
"BOOK",
"PENCIL",
"CLOCK",
"KEY",
"LAMP",
"CHAIR",
"TABLE",
"BACKPACK",
"STAR",
"HEART",
"DIAMOND",
"CROWN",
"TROPHY",
"GIFT",
"BALLOON",
"UMBRELLA",
"FOOTBALL",
"BASKETBALL",
"TENNIS BALL",
"CRICKET BAT",
"CRICKET BALL",
"FUTURE CAR",
"CYBER CITY",
"NEON TOWER",
"HOLOGRAM",
"TIME MACHINE"
)
var objectIndex =
0
while (
objectIndex < allObjectNames.length
) {
objectModel.addElement(
allObjectNames(objectIndex)
)
objectIndex += 1
}
// ============================================================
// OBJECT GEOMETRY
// ============================================================
def getObjectGeometry(
name: String
): Vector[Point] = {
val upper =
name.toUpperCase
if (
upper.indexOf("CAR") >= 0
) {
Vector(
new Point(100,470),
new Point(205,365),
new Point(390,355),
new Point(470,235),
new Point(665,235),
new Point(775,355),
new Point(900,370),
new Point(955,470),
new Point(100,470)
)
} else if (
upper.indexOf("HOUSE") >= 0 ||
upper == "VILLA" ||
upper == "PALACE" ||
upper == "CASTLE"
) {
Vector(
new Point(220,555),
new Point(220,300),
new Point(500,65),
new Point(780,300),
new Point(780,555),
new Point(220,555)
)
} else if (
upper.indexOf("TREE") >= 0
) {
Vector(
new Point(455,580),
new Point(545,580),
new Point(545,350),
new Point(680,270),
new Point(600,150),
new Point(500,215),
new Point(400,150),
new Point(320,270),
new Point(455,350),
new Point(455,580)
)
} else if (
upper == "BIRD"
) {
Vector(
new Point(190,350),
new Point(385,215),
new Point(500,300),
new Point(650,175),
new Point(815,320),
new Point(635,420),
new Point(450,400),
new Point(315,475),
new Point(190,350)
)
} else if (
upper == "FISH" ||
upper == "SHARK" ||
upper == "WHALE" ||
upper == "DOLPHIN"
) {
Vector(
new Point(140,325),
new Point(325,210),
new Point(650,210),
new Point(850,325),
new Point(650,440),
new Point(325,440),
new Point(140,325)
)
} else if (
upper.indexOf("ROCKET") >= 0 ||
upper == "UFO"
) {
Vector(
new Point(425,520),
new Point(450,220),
new Point(500,55),
new Point(550,220),
new Point(575,520),
new Point(500,595),
new Point(425,520)
)
} else if (
upper.indexOf("ROBOT") >= 0
) {
Vector(
new Point(355,555),
new Point(355,295),
new Point(335,295),
new Point(335,135),
new Point(665,135),
new Point(665,295),
new Point(645,295),
new Point(645,555),
new Point(355,555)
)
} else if (
upper.indexOf("MOUNTAIN") >= 0
) {
Vector(
new Point(40,560),
new Point(290,205),
new Point(430,400),
new Point(625,70),
new Point(960,560),
new Point(40,560)
)
} else if (
upper == "FLOWER"
) {
Vector(
new Point(500,585),
new Point(500,315),
new Point(390,225),
new Point(500,115),
new Point(610,225),
new Point(500,315),
new Point(500,585)
)
} else if (
upper == "STAR"
) {
starPoints(
5,
255
)
} else if (
upper == "HEART"
) {
heartPoints()
} else if (
upper == "CROWN"
) {
Vector(
new Point(235,490),
new Point(195,150),
new Point(390,295),
new Point(500,85),
new Point(610,295),
new Point(805,150),
new Point(765,490),
new Point(235,490)
)
} else {
polygonPoints(
6,
235,
0
)
}
}
// ============================================================
// ADD OBJECT
// ============================================================
def addObjectToCanvas(
name: String
): Unit = {
saveHistory()
val geometry =
getObjectGeometry(
name
)
drawItems +=
DrawItem(
geometry,
currentStrokeColor,
currentFillColor,
isClosedShape(geometry),
name,
true,
false
)
selectedItemIndex =
drawItems.length - 1
currentTool =
"SELECT"
repaintDrawingCanvas()
setMainStatus(
"OBJECT ADDED: " +
name
)
}
// ============================================================
// ADD SHAPE
// ============================================================
def addShapeToCanvas(
name: String
): Unit = {
saveHistory()
val geometry =
getShapeGeometry(
name
)
drawItems +=
DrawItem(
geometry,
currentStrokeColor,
currentFillColor,
isClosedShape(geometry),
name,
true,
false
)
selectedItemIndex =
drawItems.length - 1
currentTool =
"SELECT"
repaintDrawingCanvas()
setMainStatus(
"SHAPE ADDED: " +
name
)
}
// ============================================================
// CLEAR CANVAS
// ============================================================
def clearDrawing(): Unit = {
if (
drawItems.nonEmpty
) {
saveHistory()
}
drawItems.clear()
temporaryPoints.clear()
selectedItemIndex =
-1
drawingCodeArea.setText(
"// CANVAS CLEARED"
)
repaintDrawingCanvas()
setMainStatus(
"CANVAS CLEARED"
)
}
// ============================================================
// BUCKET FILL
// ============================================================
def bucketFillSelected(): Unit = {
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length
) {
val oldItem =
drawItems(
selectedItemIndex
)
if (
isClosedShape(
oldItem.points
)
) {
saveHistory()
drawItems(
selectedItemIndex
) =
oldItem.copy(
fillColor =
currentFillColor,
filled =
true
)
repaintDrawingCanvas()
setMainStatus(
"BUCKET FILL COMPLETE"
)
} else {
setMainStatus(
"CLOSED OBJECT REQUIRED"
)
}
} else {
setMainStatus(
"SELECT OBJECT FIRST"
)
}
}
// ============================================================
// COLOR NAME
// ============================================================
def kojoColorName(
c: Color
): String = {
val red =
c.getRed
val green =
c.getGreen
val blue =
c.getBlue
if (
red > 220 &&
green < 100 &&
blue < 100
) {
"red"
} else if (
red < 100 &&
green > 170 &&
blue < 120
) {
"green"
} else if (
red < 100 &&
green < 150 &&
blue > 170
) {
"blue"
} else if (
red > 220 &&
green > 170 &&
blue < 130
) {
"yellow"
} else if (
red > 220 &&
green > 100 &&
blue < 110
) {
"orange"
} else if (
red > 150 &&
blue > 150
) {
"magenta"
} else {
"black"
}
}
// ============================================================
// DRAWING CODE
// ============================================================
def generateDrawingCode(): Unit = {
val builder =
new StringBuilder()
builder.append(
"// ULTRA LEGEND GENERATED KOJO CODE\n"
)
builder.append(
"cleari()\n"
)
builder.append(
"setAnimationDelay(5)\n\n"
)
if (
drawItems.isEmpty
) {
builder.append(
"// NOTHING DRAWN\n"
)
} else {
var i =
0
while (
i < drawItems.length
) {
val item =
drawItems(i)
if (
item.visible &&
item.points.nonEmpty
) {
builder.append(
"// OBJECT " +
item.itemName +
"\n"
)
builder.append(
"setPenColor(" +
kojoColorName(
item.strokeColor
) +
")\n"
)
builder.append(
"penUp()\n"
)
builder.append(
"setPosition(" +
(
item.points.head.x -
CENTER_X
) +
", " +
(
CENTER_Y -
item.points.head.y
) +
")\n"
)
builder.append(
"penDown()\n"
)
var j =
1
while (
j < item.points.length
) {
builder.append(
"lineTo(" +
(
item.points(j).x -
CENTER_X
) +
", " +
(
CENTER_Y -
item.points(j).y
) +
")\n"
)
j += 1
}
builder.append(
"\n"
)
}
i += 1
}
}
generatedDrawingCode =
builder.toString
drawingCodeArea.setText(
generatedDrawingCode
)
setMainStatus(
"EXACT DRAWING CODE GENERATED"
)
}
// ============================================================
// COPY TEXT
// ============================================================
def copyGeneratedText(
text: String
): Unit = {
try {
val clipboard =
java.awt.Toolkit
.getDefaultToolkit
.getSystemClipboard
clipboard.setContents(
new java.awt.datatransfer.StringSelection(
text
),
null
)
setMainStatus(
"CODE COPIED"
)
} catch {
case _: Exception =>
setMainStatus(
"COPY FAILED"
)
}
}
// ============================================================
// SAVE TEXT
// ============================================================
def saveGeneratedText(
text: String
): Unit = {
val chooser =
new JFileChooser()
chooser.setDialogTitle(
"SAVE GENERATED CODE"
)
if (
chooser.showSaveDialog(
mainFrame
) ==
JFileChooser.APPROVE_OPTION
) {
try {
var file =
chooser.getSelectedFile
if (
!file.getName
.toLowerCase
.endsWith(
".scala"
)
) {
file =
new java.io.File(
file.getAbsolutePath +
".scala"
)
}
val writer =
new java.io.PrintWriter(
file
)
writer.write(
text
)
writer.close()
setMainStatus(
"CODE SAVED"
)
} catch {
case _: Exception =>
setMainStatus(
"SAVE ERROR"
)
}
}
}
// ============================================================
// GAME LIST
// ============================================================
val gameNames =
Array(
"SLING BALL",
"POTION ADVENTURE",
"UNBEATABLE TIC TAC TOE",
"PONG",
"SNAKE",
"BREAKOUT",
"FLAPPY BIRD",
"CAR DODGE",
"SPACE SHOOTER",
"TARGET SHOOTER",
"BALL CATCH",
"BALL MAZE",
"MEMORY MATCH",
"CLICK RUSH",
"DODGE FIELD"
)
val gameDescriptions =
Array(
"Launch the ball and draw paddles to guide it to the target.",
"Collect the potion and reach the green goal.",
"Mouse Tic Tac Toe against the computer.",
"Mouse controlled paddle and bouncing ball.",
"Mouse controlled snake game.",
"Mouse controlled paddle and block breaker.",
"Mouse controlled flying bird game.",
"Mouse controlled car dodging traffic.",
"Mouse controlled space ship and shooting.",
"Click targets before the timer ends.",
"Move the basket and catch falling balls.",
"Drag the ball through a maze.",
"Match identical cards.",
"Click the target as many times as possible.",
"Move the player and avoid falling enemies."
)
// ============================================================
// AUTO GAME
// ============================================================
def autoGameFromDrawing(): String = {
var result =
"SLING BALL"
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length
) {
val name =
drawItems(
selectedItemIndex
).itemName.toUpperCase
if (
name.indexOf("CAR") >= 0 ||
name.indexOf("BUS") >= 0 ||
name.indexOf("TRUCK") >= 0
) {
result =
"CAR DODGE"
} else if (
name.indexOf("BIRD") >= 0
) {
result =
"FLAPPY BIRD"
} else if (
name.indexOf("ROCKET") >= 0 ||
name.indexOf("UFO") >= 0 ||
name.indexOf("PLANET") >= 0
) {
result =
"SPACE SHOOTER"
} else if (
name.indexOf("BALL") >= 0 ||
name.indexOf("FOOTBALL") >= 0 ||
name.indexOf("BASKETBALL") >= 0
) {
result =
"BALL CATCH"
} else if (
name.indexOf("STAR") >= 0
) {
result =
"TARGET SHOOTER"
}
}
result
}
// ============================================================
// GAME CODE
// ============================================================
def createGameSource(
gameName: String
): String = {
val builder =
new StringBuilder()
builder.append(
"// ===============================================\n"
)
builder.append(
"// ULTRA LEGEND GAME STUDIO GENERATED SOURCE\n"
)
builder.append(
"// GAME: " +
gameName +
"\n"
)
builder.append(
"// ===============================================\n\n"
)
builder.append(
"cleari()\n"
)
builder.append(
"setAnimationDelay(5)\n\n"
)
if (
gameName == "SLING BALL"
) {
builder.append(
"// Drag the ball to launch it.\n"
)
builder.append(
"// Draw paddles with the mouse.\n"
)
} else if (
gameName == "POTION ADVENTURE"
) {
builder.append(
"// Player movement, jumping, potion and goal.\n"
)
} else if (
gameName == "UNBEATABLE TIC TAC TOE"
) {
builder.append(
"// Mouse board + computer decision logic.\n"
)
} else if (
gameName == "PONG"
) {
builder.append(
"// Mouse paddle + animated ball.\n"
)
} else if (
gameName == "SNAKE"
) {
builder.append(
"// Mouse direction + growing snake.\n"
)
} else if (
gameName == "BREAKOUT"
) {
builder.append(
"// Mouse paddle + blocks.\n"
)
} else if (
gameName == "FLAPPY BIRD"
) {
builder.append(
"// Mouse click flap mechanic.\n"
)
} else if (
gameName == "CAR DODGE"
) {
builder.append(
"// Mouse car movement + traffic.\n"
)
} else if (
gameName == "SPACE SHOOTER"
) {
builder.append(
"// Mouse ship movement + firing.\n"
)
} else if (
gameName == "TARGET SHOOTER"
) {
builder.append(
"// Mouse target clicking.\n"
)
} else if (
gameName == "BALL CATCH"
) {
builder.append(
"// Mouse basket movement.\n"
)
} else if (
gameName == "BALL MAZE"
) {
builder.append(
"// Mouse drag maze game.\n"
)
} else if (
gameName == "MEMORY MATCH"
) {
builder.append(
"// Mouse card matching.\n"
)
} else if (
gameName == "CLICK RUSH"
) {
builder.append(
"// Fast target clicking.\n"
)
} else {
builder.append(
"// Mouse player movement and enemy avoidance.\n"
)
}
builder.toString
}
// ============================================================
// GAME WINDOW
// ============================================================
def createGameFrame(
title: String
): JFrame = {
val result =
new JFrame(
title
)
result.setDefaultCloseOperation(
WindowConstants.DISPOSE_ON_CLOSE
)
result.setSize(
900,
650
)
result.setLocationRelativeTo(
mainFrame
)
result
}
// ============================================================
// SLING BALL
// ============================================================
def launchSlingBall(): Unit = {
val gameFrame =
createGameFrame(
"SLING BALL - MOUSE"
)
var ballX =
100.0
var ballY =
500.0
var velocityX =
0.0
var velocityY =
0.0
var ballLaunched =
false
var gameWon =
false
var aimX =
100.0
var aimY =
500.0
val target =
new java.awt.Rectangle(
760,
80,
70,
70
)
val obstacles =
Array(
new java.awt.Rectangle(
280,
190,
190,
20
),
new java.awt.Rectangle(
540,
320,
190,
20
),
new java.awt.Rectangle(
360,
470,
200,
20
)
)
val paddles =
ArrayBuffer[PaddleLine]()
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
g2.setPaint(
new GradientPaint(
0,
0,
new Color(
35,
90,
140
),
0,
getHeight,
new Color(
10,
20,
45
)
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
new Color(
255,
70,
70
)
)
g2.fillOval(
target.x,
target.y,
target.width,
target.height
)
g2.setColor(
new Color(
150,
110,
60
)
)
var i =
0
while (
i < obstacles.length
) {
g2.fillRect(
obstacles(i).x,
obstacles(i).y,
obstacles(i).width,
obstacles(i).height
)
i += 1
}
g2.setColor(
Color.YELLOW
)
g2.setStroke(
new BasicStroke(
9,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
i =
0
while (
i < paddles.length
) {
val line =
paddles(i)
g2.drawLine(
line.p1.x,
line.p1.y,
line.p2.x,
line.p2.y
)
i += 1
}
g2.setColor(
Color.RED
)
g2.fillOval(
ballX.toInt - 10,
ballY.toInt - 10,
20,
20
)
if (
!ballLaunched
) {
g2.setColor(
Color.GREEN
)
g2.drawLine(
ballX.toInt,
ballY.toInt,
aimX.toInt,
aimY.toInt
)
}
g2.setColor(
Color.WHITE
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
18
)
)
g2.drawString(
if (
gameWon
)
"YOU WIN!"
else
"DRAG TO LAUNCH - DRAW PADDLES AFTER LAUNCH",
20,
30
)
}
}
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
if (
!ballLaunched
) {
aimX =
e.getX
aimY =
e.getY
} else {
if (
e.getY <
panel.getHeight - 45
) {
paddles +=
PaddleLine(
new Point(
e.getX - 45,
e.getY
),
new Point(
e.getX + 45,
e.getY
)
)
}
}
panel.repaint()
}
override def mouseReleased(
e: MouseEvent
): Unit = {
if (
!ballLaunched
) {
velocityX =
(
ballX -
e.getX
) *
0.08
velocityY =
(
ballY -
e.getY
) *
0.08
ballLaunched =
true
}
}
}
)
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
if (
!ballLaunched
) {
aimX =
e.getX
aimY =
e.getY
panel.repaint()
}
}
}
)
val timer =
new Timer(
25,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
if (
ballLaunched &&
!gameWon
) {
velocityY +=
0.25
ballX +=
velocityX
ballY +=
velocityY
if (
ballX < 10 ||
ballX >
panel.getWidth - 10
) {
velocityX =
-velocityX
}
if (
ballY < 10
) {
velocityY =
-velocityY
}
if (
ballY >
panel.getHeight
) {
ballX =
100
ballY =
500
velocityX =
0
velocityY =
0
ballLaunched =
false
}
var i =
0
while (
i < obstacles.length
) {
if (
obstacles(i).contains(
ballX.toInt,
ballY.toInt
)
) {
velocityY =
-math.abs(
velocityY
)
}
i += 1
}
i =
0
while (
i < paddles.length
) {
val paddleLine =
paddles(i)
val minX =
math.min(
paddleLine.p1.x,
paddleLine.p2.x
) - 10
val maxX =
math.max(
paddleLine.p1.x,
paddleLine.p2.x
) + 10
if (
ballX >= minX &&
ballX <= maxX &&
ballY >=
paddleLine.p1.y - 12 &&
ballY <=
paddleLine.p1.y + 12
) {
velocityY =
-math.abs(
velocityY
)
}
i += 1
}
if (
target.contains(
ballX.toInt,
ballY.toInt
)
) {
gameWon =
true
}
panel.repaint()
}
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// TIC TAC TOE
// ============================================================
def launchTicTacToe(): Unit = {
val gameFrame =
createGameFrame(
"UNBEATABLE TIC TAC TOE"
)
val board =
Array.fill[Int](
9
)(
0
)
var humanTurn =
true
var gameFinished =
false
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
245,
248,
255
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.BLACK
)
g2.setStroke(
new BasicStroke(
6
)
)
var i =
1
while (
i < 3
) {
g2.drawLine(
i *
getWidth /
3,
70,
i *
getWidth /
3,
getHeight
)
g2.drawLine(
0,
70 +
i *
(
getHeight -
70
) /
3,
getWidth,
70 +
i *
(
getHeight -
70
) /
3
)
i += 1
}
g2.setFont(
new Font(
"Arial",
Font.BOLD,
80
)
)
i =
0
while (
i < 9
) {
if (
board(i) != 0
) {
g2.setColor(
if (
board(i) == 1
)
Color.BLUE
else
Color.RED
)
val px =
(
i % 3
) *
getWidth /
3 +
68
val py =
70 +
(
i / 3
) *
(
getHeight -
70
) /
3 +
102
g2.drawString(
if (
board(i) == 1
)
"X"
else
"O",
px,
py
)
}
i += 1
}
g2.setColor(
Color.DARK_GRAY
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
19
)
)
g2.drawString(
if (
gameFinished
)
"GAME OVER - RESET"
else if (
humanTurn
)
"YOUR TURN"
else
"COMPUTER TURN",
20,
35
)
}
}
def winningPlayer(
player: Int
): Boolean = {
val lines =
Array(
Array(0,1,2),
Array(3,4,5),
Array(6,7,8),
Array(0,3,6),
Array(1,4,7),
Array(2,5,8),
Array(0,4,8),
Array(2,4,6)
)
var found =
false
var i =
0
while (
i < lines.length
) {
if (
board(
lines(i)(0)
) == player &&
board(
lines(i)(1)
) == player &&
board(
lines(i)(2)
) == player
) {
found =
true
}
i += 1
}
found
}
def boardFull(): Boolean = {
var result =
true
var i =
0
while (
i < 9
) {
if (
board(i) == 0
) {
result =
false
}
i += 1
}
result
}
def minimax(
maximize: Boolean
): Int = {
if (
winningPlayer(2)
) {
10
} else if (
winningPlayer(1)
) {
-10
} else if (
boardFull()
) {
0
} else {
var best =
if (
maximize
)
-100
else
100
var i =
0
while (
i < 9
) {
if (
board(i) == 0
) {
board(i) =
if (
maximize
)
2
else
1
val value =
minimax(
!maximize
)
board(i) =
0
if (
maximize
) {
if (
value > best
) {
best =
value
}
} else {
if (
value < best
) {
best =
value
}
}
}
i += 1
}
best
}
}
def makeComputerMove(): Unit = {
var bestIndex =
-1
var bestValue =
-100
var i =
0
while (
i < 9
) {
if (
board(i) == 0
) {
board(i) =
2
val value =
minimax(
false
)
board(i) =
0
if (
value > bestValue
) {
bestValue =
value
bestIndex =
i
}
}
i += 1
}
if (
bestIndex >= 0
) {
board(
bestIndex
) =
2
}
}
panel.addMouseListener(
new MouseAdapter {
override def mouseClicked(
e: MouseEvent
): Unit = {
if (
humanTurn &&
!gameFinished &&
e.getY >= 70
) {
val column =
math.max(
0,
math.min(
2,
e.getX /
math.max(
1,
panel.getWidth / 3
)
)
)
val row =
math.max(
0,
math.min(
2,
(
e.getY -
70
) /
math.max(
1,
(
panel.getHeight -
70
) /
3
)
)
)
val index =
row * 3 +
column
if (
board(index) == 0
) {
board(index) =
1
if (
winningPlayer(1) ||
boardFull()
) {
gameFinished =
true
} else {
humanTurn =
false
makeComputerMove()
if (
winningPlayer(2) ||
boardFull()
) {
gameFinished =
true
} else {
humanTurn =
true
}
}
panel.repaint()
}
}
}
}
)
val resetButton =
createButton(
"RESET"
)
resetButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
var i =
0
while (
i < 9
) {
board(i) =
0
i += 1
}
humanTurn =
true
gameFinished =
false
panel.repaint()
}
}
)
gameFrame.add(
panel,
BorderLayout.CENTER
)
gameFrame.add(
resetButton,
BorderLayout.SOUTH
)
gameFrame.setVisible(
true
)
}
// ============================================================
// PONG
// ============================================================
def launchPong(): Unit = {
val gameFrame =
createGameFrame(
"PONG - MOUSE"
)
var paddleX =
350.0
var ballX =
420.0
var ballY =
250.0
var speedX =
5.0
var speedY =
4.0
var score =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
Color.BLACK
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.WHITE
)
g2.fillOval(
ballX.toInt - 10,
ballY.toInt - 10,
20,
20
)
g2.fillRoundRect(
paddleX.toInt,
getHeight - 60,
150,
20,
10,
10
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
20
)
)
g2.drawString(
"SCORE: " +
score,
20,
30
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
paddleX =
math.max(
0,
math.min(
panel.getWidth - 150,
e.getX - 75
)
)
}
}
)
val timer =
new Timer(
25,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
ballX +=
speedX
ballY +=
speedY
if (
ballX < 10 ||
ballX >
panel.getWidth - 10
) {
speedX =
-speedX
}
if (
ballY < 10
) {
speedY =
-speedY
}
if (
ballY >
panel.getHeight - 80 &&
ballX >= paddleX &&
ballX <=
paddleX + 150
) {
speedY =
-math.abs(
speedY
)
score +=
1
}
if (
ballY >
panel.getHeight
) {
ballX =
panel.getWidth / 2
ballY =
panel.getHeight / 2
score =
0
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// SNAKE - FULLY FIXED
// ============================================================
def launchSnake(): Unit = {
val gameFrame =
createGameFrame(
"SNAKE - MOUSE CONTROL"
)
val cellSize =
25
val snakeBody =
ArrayBuffer[Point]()
snakeBody +=
new Point(10,10)
snakeBody +=
new Point(9,10)
snakeBody +=
new Point(8,10)
var foodPoint =
new Point(
15,
10
)
var directionX =
1
var directionY =
0
var snakeScore =
0
var snakeRunning =
true
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
// BACKGROUND
g2.setColor(
new Color(
15,
45,
22
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
// GRID
g2.setColor(
new Color(
255,
255,
255,
18
)
)
var gridX =
0
while (
gridX <= getWidth
) {
g2.drawLine(
gridX,
0,
gridX,
getHeight
)
gridX +=
cellSize
}
var gridY =
0
while (
gridY <= getHeight
) {
g2.drawLine(
0,
gridY,
getWidth,
gridY
)
gridY +=
cellSize
}
// FOOD
g2.setColor(
Color.RED
)
g2.fillOval(
foodPoint.x *
cellSize +
3,
foodPoint.y *
cellSize +
3,
cellSize - 6,
cellSize - 6
)
// SNAKE
var snakeIndex =
0
while (
snakeIndex <
snakeBody.length
) {
if (
snakeIndex == 0
) {
g2.setColor(
new Color(
80,
245,
100
)
)
} else {
g2.setColor(
new Color(
35,
175,
65
)
)
}
g2.fillRoundRect(
snakeBody(
snakeIndex
).x *
cellSize +
2,
snakeBody(
snakeIndex
).y *
cellSize +
2,
cellSize - 4,
cellSize - 4,
8,
8
)
snakeIndex +=
1
}
// TEXT
g2.setColor(
Color.WHITE
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
20
)
)
g2.drawString(
"SCORE: " +
snakeScore,
12,
26
)
g2.drawString(
"MOVE MOUSE",
180,
26
)
// GAME OVER
if (
!snakeRunning
) {
g2.setColor(
new Color(
0,
0,
0,
170
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.WHITE
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
42
)
)
g2.drawString(
"GAME OVER",
math.max(
20,
getWidth / 2 - 140
),
getHeight / 2
)
}
}
}
// ========================================================
// MOUSE CONTROL
// ========================================================
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
if (
snakeRunning &&
snakeBody.nonEmpty
) {
val head =
snakeBody.head
val headPixelX =
head.x *
cellSize
val headPixelY =
head.y *
cellSize
val differenceX =
e.getX -
headPixelX
val differenceY =
e.getY -
headPixelY
if (
math.abs(
differenceX
) >
math.abs(
differenceY
)
) {
if (
differenceX > 0 &&
directionX != -1
) {
directionX =
1
directionY =
0
} else if (
differenceX < 0 &&
directionX != 1
) {
directionX =
-1
directionY =
0
}
} else {
if (
differenceY > 0 &&
directionY != -1
) {
directionX =
0
directionY =
1
} else if (
differenceY < 0 &&
directionY != 1
) {
directionX =
0
directionY =
-1
}
}
}
}
}
)
// ========================================================
// RESET
// ========================================================
val resetButton =
createButton(
"RESET"
)
resetButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
snakeBody.clear()
snakeBody +=
new Point(
10,
10
)
snakeBody +=
new Point(
9,
10
)
snakeBody +=
new Point(
8,
10
)
foodPoint =
new Point(
15,
10
)
directionX =
1
directionY =
0
snakeScore =
0
snakeRunning =
true
panel.repaint()
}
}
)
// ========================================================
// TIMER
// ========================================================
val snakeTimer =
new Timer(
120,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
if (
snakeRunning &&
snakeBody.nonEmpty
) {
val currentHead =
snakeBody.head
val nextX =
currentHead.x +
directionX
val nextY =
currentHead.y +
directionY
val columnCount =
math.max(
1,
panel.getWidth /
cellSize
)
val rowCount =
math.max(
1,
panel.getHeight /
cellSize
)
// WALL COLLISION
if (
nextX < 0 ||
nextY < 0 ||
nextX >= columnCount ||
nextY >= rowCount
) {
snakeRunning =
false
} else {
val nextHead =
new Point(
nextX,
nextY
)
// SELF COLLISION
var selfCollision =
false
var bodyIndex =
0
while (
bodyIndex <
snakeBody.length
) {
if (
snakeBody(
bodyIndex
).x ==
nextHead.x &&
snakeBody(
bodyIndex
).y ==
nextHead.y
) {
selfCollision =
true
}
bodyIndex +=
1
}
if (
selfCollision
) {
snakeRunning =
false
} else {
snakeBody.prepend(
nextHead
)
// FOOD
if (
nextHead.x ==
foodPoint.x &&
nextHead.y ==
foodPoint.y
) {
snakeScore +=
1
var newFoodFound =
false
var newFoodX =
0
var newFoodY =
0
while (
!newFoodFound
) {
newFoodX =
(
math.random *
columnCount
).toInt
newFoodY =
(
math.random *
rowCount
).toInt
newFoodFound =
true
var checkIndex =
0
while (
checkIndex <
snakeBody.length
) {
if (
snakeBody(
checkIndex
).x ==
newFoodX &&
snakeBody(
checkIndex
).y ==
newFoodY
) {
newFoodFound =
false
}
checkIndex +=
1
}
}
foodPoint =
new Point(
newFoodX,
newFoodY
)
} else {
snakeBody.remove(
snakeBody.length - 1
)
}
}
}
panel.repaint()
}
}
}
)
snakeTimer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
snakeTimer.stop()
}
}
)
gameFrame.add(
panel,
BorderLayout.CENTER
)
gameFrame.add(
resetButton,
BorderLayout.SOUTH
)
gameFrame.setVisible(
true
)
}
// ============================================================
// BREAKOUT
// ============================================================
def launchBreakout(): Unit = {
val gameFrame =
createGameFrame(
"BREAKOUT - MOUSE"
)
var paddleX =
350.0
var ballX =
430.0
var ballY =
400.0
var ballDX =
4.0
var ballDY =
-4.0
var breakoutScore =
0
val blocks =
ArrayBuffer[Point]()
var row =
0
while (
row < 5
) {
var column =
0
while (
column < 10
) {
blocks +=
new Point(
40 +
column *
75,
60 +
row *
30
)
column +=
1
}
row +=
1
}
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
18,
18,
40
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.WHITE
)
g2.fillOval(
ballX.toInt - 9,
ballY.toInt - 9,
18,
18
)
g2.setColor(
Color.CYAN
)
g2.fillRoundRect(
paddleX.toInt,
getHeight - 55,
150,
18,
10,
10
)
g2.setColor(
Color.ORANGE
)
var i =
0
while (
i < blocks.length
) {
g2.fillRect(
blocks(i).x,
blocks(i).y,
65,
22
)
i +=
1
}
g2.setColor(
Color.WHITE
)
g2.drawString(
"SCORE: " +
breakoutScore,
20,
28
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
paddleX =
math.max(
0,
math.min(
panel.getWidth - 150,
e.getX - 75
)
)
}
}
)
val timer =
new Timer(
25,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
ballX +=
ballDX
ballY +=
ballDY
if (
ballX < 10 ||
ballX >
panel.getWidth - 10
) {
ballDX =
-ballDX
}
if (
ballY < 10
) {
ballDY =
-ballDY
}
if (
ballY >
panel.getHeight - 75 &&
ballX >= paddleX &&
ballX <=
paddleX + 150
) {
ballDY =
-math.abs(
ballDY
)
}
var hitBlock =
-1
var i =
0
while (
i < blocks.length
) {
if (
ballX >=
blocks(i).x &&
ballX <=
blocks(i).x + 65 &&
ballY >=
blocks(i).y &&
ballY <=
blocks(i).y + 22
) {
hitBlock =
i
}
i +=
1
}
if (
hitBlock >= 0
) {
blocks.remove(
hitBlock
)
ballDY =
-ballDY
breakoutScore +=
1
}
if (
ballY >
panel.getHeight
) {
ballX =
panel.getWidth / 2
ballY =
panel.getHeight / 2
ballDX =
4
ballDY =
-4
breakoutScore =
0
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// FLAPPY BIRD
// ============================================================
def launchFlappy(): Unit = {
val gameFrame =
createGameFrame(
"FLAPPY BIRD - MOUSE"
)
var birdY =
280.0
var birdVelocity =
0.0
var pipeX =
820.0
var gapY =
280.0
var flappyScore =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setPaint(
new GradientPaint(
0,
0,
new Color(
65,
190,
255
),
0,
getHeight,
Color.WHITE
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.YELLOW
)
g2.fillOval(
150,
birdY.toInt,
45,
35
)
g2.setColor(
Color.GREEN
)
g2.fillRect(
pipeX.toInt,
0,
70,
gapY.toInt - 85
)
g2.fillRect(
pipeX.toInt,
gapY.toInt + 85,
70,
getHeight
)
g2.setColor(
Color.BLACK
)
g2.drawString(
"CLICK TO FLAP SCORE: " +
flappyScore,
20,
30
)
}
}
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
birdVelocity =
-9.0
}
}
)
val timer =
new Timer(
25,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
birdVelocity +=
0.40
birdY +=
birdVelocity
pipeX -=
5
if (
pipeX <
-80
) {
pipeX =
panel.getWidth + 20
gapY =
170 +
math.random *
230
flappyScore +=
1
}
if (
birdY < 0 ||
birdY >
panel.getHeight
) {
birdY =
280
birdVelocity =
0
pipeX =
panel.getWidth
flappyScore =
0
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// CAR DODGE
// ============================================================
def launchCarDodge(): Unit = {
val gameFrame =
createGameFrame(
"CAR DODGE - MOUSE"
)
var playerCarX =
400.0
var enemyCarX =
200.0
var enemyCarY =
-100.0
var carScore =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
55,
55,
60
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.WHITE
)
var roadY =
0
while (
roadY <
getHeight
) {
g2.fillRect(
getWidth / 2 - 5,
roadY,
10,
60
)
roadY +=
100
}
g2.setColor(
Color.BLUE
)
g2.fillRoundRect(
playerCarX.toInt,
getHeight - 120,
60,
100,
18,
18
)
g2.setColor(
Color.RED
)
g2.fillRoundRect(
enemyCarX.toInt,
enemyCarY.toInt,
60,
100,
18,
18
)
g2.setColor(
Color.WHITE
)
g2.drawString(
"SCORE: " +
carScore,
20,
28
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
playerCarX =
math.max(
0,
math.min(
panel.getWidth - 60,
e.getX - 30
)
)
}
}
)
val timer =
new Timer(
25,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
enemyCarY +=
7
if (
enemyCarY >
panel.getHeight
) {
enemyCarY =
-100
enemyCarX =
math.random *
math.max(
1,
panel.getWidth - 60
)
carScore +=
1
}
val hit =
enemyCarX + 60 >
playerCarX &&
enemyCarX <
playerCarX + 60 &&
enemyCarY + 100 >
panel.getHeight - 120 &&
enemyCarY <
panel.getHeight
if (
hit
) {
carScore =
0
enemyCarY =
-100
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// SPACE SHOOTER
// ============================================================
def launchSpaceShooter(): Unit = {
val gameFrame =
createGameFrame(
"SPACE SHOOTER - MOUSE"
)
var shipX =
400.0
var enemyX =
300.0
var enemyY =
70.0
var laserX =
-100.0
var laserY =
-100.0
var shooterScore =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
5,
10,
30
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.WHITE
)
var starIndex =
0
while (
starIndex < 70
) {
g2.fillOval(
(
starIndex *
71
) %
math.max(
1,
getWidth
),
(
starIndex *
43
) %
math.max(
1,
getHeight
),
2,
2
)
starIndex +=
1
}
g2.setColor(
Color.CYAN
)
val ship =
new java.awt.Polygon()
ship.addPoint(
shipX.toInt,
getHeight - 90
)
ship.addPoint(
shipX.toInt + 25,
getHeight - 140
)
ship.addPoint(
shipX.toInt + 50,
getHeight - 90
)
g2.fillPolygon(
ship
)
g2.setColor(
Color.RED
)
g2.fillOval(
enemyX.toInt,
enemyY.toInt,
45,
35
)
g2.setColor(
Color.YELLOW
)
if (
laserY >
-50
) {
g2.fillRect(
laserX.toInt,
laserY.toInt,
6,
20
)
}
g2.setColor(
Color.WHITE
)
g2.drawString(
"MOVE + CLICK SCORE: " +
shooterScore,
20,
30
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
shipX =
math.max(
0,
math.min(
panel.getWidth - 50,
e.getX - 25
)
)
}
}
)
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
laserX =
shipX + 22
laserY =
panel.getHeight - 150
}
}
)
val timer =
new Timer(
25,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
enemyY +=
2
laserY -=
12
if (
laserX >= enemyX &&
laserX <= enemyX + 45 &&
laserY <= enemyY + 35 &&
laserY >= enemyY - 20
) {
shooterScore +=
1
enemyX =
math.random *
math.max(
1,
panel.getWidth - 45
)
enemyY =
50
}
if (
enemyY >
panel.getHeight
) {
enemyY =
50
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// TARGET SHOOTER
// ============================================================
def launchTargetShooter(): Unit = {
val gameFrame =
createGameFrame(
"TARGET SHOOTER - MOUSE"
)
var targetX =
350.0
var targetY =
250.0
var targetScore =
0
var targetTime =
30
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
18,
24,
55
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.RED
)
g2.fillOval(
targetX.toInt,
targetY.toInt,
80,
80
)
g2.setColor(
Color.WHITE
)
g2.drawOval(
targetX.toInt + 18,
targetY.toInt + 18,
44,
44
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
20
)
)
g2.drawString(
"SCORE: " +
targetScore +
" TIME: " +
targetTime,
20,
30
)
}
}
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
if (
e.getX >= targetX &&
e.getX <= targetX + 80 &&
e.getY >= targetY &&
e.getY <= targetY + 80
) {
targetScore +=
1
targetX =
math.random *
math.max(
1,
panel.getWidth - 80
)
targetY =
60 +
math.random *
math.max(
1,
panel.getHeight - 140
)
panel.repaint()
}
}
}
)
val timer =
new Timer(
1000,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
targetTime -=
1
if (
targetTime <=
0
) {
targetTime =
30
targetScore =
0
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// BALL CATCH
// ============================================================
def launchBallCatch(): Unit = {
val gameFrame =
createGameFrame(
"BALL CATCH - MOUSE"
)
var basketX =
350.0
var fallingBallX =
200.0
var fallingBallY =
-50.0
var catchScore =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setPaint(
new GradientPaint(
0,
0,
new Color(
30,
120,
220
),
0,
getHeight,
new Color(
175,
235,
255
)
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.YELLOW
)
g2.fillOval(
fallingBallX.toInt,
fallingBallY.toInt,
35,
35
)
g2.setColor(
new Color(
145,
80,
20
)
)
g2.fillRoundRect(
basketX.toInt,
getHeight - 80,
150,
35,
15,
15
)
g2.setColor(
Color.WHITE
)
g2.drawString(
"SCORE: " +
catchScore,
20,
30
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
basketX =
math.max(
0,
math.min(
panel.getWidth - 150,
e.getX - 75
)
)
}
}
)
val timer =
new Timer(
30,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
fallingBallY +=
6
if (
fallingBallY >
panel.getHeight - 110
) {
if (
fallingBallX + 35 >= basketX &&
fallingBallX <= basketX + 150
) {
catchScore +=
1
}
fallingBallX =
math.random *
math.max(
1,
panel.getWidth - 35
)
fallingBallY =
-40
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// BALL MAZE
// ============================================================
def launchBallMaze(): Unit = {
val gameFrame =
createGameFrame(
"BALL MAZE - MOUSE"
)
var mazeBallX =
80.0
var mazeBallY =
80.0
val mazeTarget =
new java.awt.Rectangle(
730,
490,
60,
60
)
val mazeWalls =
Array(
new java.awt.Rectangle(
180,
100,
520,
20
),
new java.awt.Rectangle(
180,
100,
20,
300
),
new java.awt.Rectangle(
430,
220,
20,
300
),
new java.awt.Rectangle(
700,
100,
20,
420
)
)
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
245,
245,
250
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
new Color(
65,
65,
75
)
)
var i =
0
while (
i < mazeWalls.length
) {
g2.fillRect(
mazeWalls(i).x,
mazeWalls(i).y,
mazeWalls(i).width,
mazeWalls(i).height
)
i +=
1
}
g2.setColor(
Color.GREEN
)
g2.fillOval(
mazeTarget.x,
mazeTarget.y,
mazeTarget.width,
mazeTarget.height
)
g2.setColor(
Color.RED
)
g2.fillOval(
mazeBallX.toInt,
mazeBallY.toInt,
35,
35
)
g2.setColor(
Color.BLACK
)
g2.drawString(
"DRAG RED BALL TO GREEN TARGET",
20,
30
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseDragged(
e: MouseEvent
): Unit = {
val nx =
e.getX - 17
val ny =
e.getY - 17
val ballRectangle =
new java.awt.Rectangle(
nx,
ny,
35,
35
)
var collision =
false
var i =
0
while (
i < mazeWalls.length
) {
if (
mazeWalls(i)
.intersects(
ballRectangle
)
) {
collision =
true
}
i += 1
}
if (
!collision
) {
mazeBallX =
math.max(
0,
math.min(
panel.getWidth - 35,
nx
)
)
mazeBallY =
math.max(
0,
math.min(
panel.getHeight - 35,
ny
)
)
}
if (
mazeTarget.contains(
mazeBallX.toInt + 17,
mazeBallY.toInt + 17
)
) {
JOptionPane.showMessageDialog(
gameFrame,
"YOU WIN!"
)
}
panel.repaint()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// MEMORY MATCH
// ============================================================
def launchMemoryMatch(): Unit = {
val gameFrame =
createGameFrame(
"MEMORY MATCH"
)
val cards =
Array(
"A","A",
"B","B",
"C","C",
"D","D",
"E","E",
"F","F"
)
val shuffledCards =
scala.util.Random
.shuffle(
cards.toSeq
)
.toArray
val revealed =
Array.fill[Boolean](
12
)(
false
)
var firstCard =
-1
var secondCard =
-1
var matchedPairs =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
30,
45,
85
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
38
)
)
var i =
0
while (
i < 12
) {
val column =
i % 4
val row =
i / 4
val cardX =
110 +
column *
175
val cardY =
95 +
row *
125
g2.setColor(
if (
revealed(i)
)
Color.WHITE
else
new Color(
80,
125,
215
)
)
g2.fillRoundRect(
cardX,
cardY,
130,
95,
15,
15
)
if (
revealed(i)
) {
g2.setColor(
Color.BLACK
)
g2.drawString(
shuffledCards(i),
cardX + 50,
cardY + 62
)
}
i +=
1
}
g2.setColor(
Color.WHITE
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
20
)
)
g2.drawString(
"MATCHES: " +
matchedPairs +
" / 6",
20,
30
)
}
}
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
val column =
(
e.getX - 110
) /
175
val row =
(
e.getY - 95
) /
125
if (
column >= 0 &&
column < 4 &&
row >= 0 &&
row < 3
) {
val index =
row * 4 +
column
if (
!revealed(index)
) {
if (
firstCard < 0
) {
firstCard =
index
revealed(index) =
true
} else if (
secondCard < 0 &&
index != firstCard
) {
secondCard =
index
revealed(index) =
true
if (
shuffledCards(
firstCard
) ==
shuffledCards(
secondCard
)
) {
matchedPairs +=
1
firstCard =
-1
secondCard =
-1
} else {
val hideTimer =
new Timer(
500,
new ActionListener {
override def actionPerformed(
event: ActionEvent
): Unit = {
revealed(
firstCard
) =
false
revealed(
secondCard
) =
false
firstCard =
-1
secondCard =
-1
panel.repaint()
}
}
)
hideTimer.setRepeats(
false
)
hideTimer.start()
}
}
panel.repaint()
}
}
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// CLICK RUSH
// ============================================================
def launchClickRush(): Unit = {
val gameFrame =
createGameFrame(
"CLICK RUSH"
)
var clickX =
300.0
var clickY =
250.0
var clicks =
0
var secondsLeft =
20
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
15,
25,
55
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.ORANGE
)
g2.fillOval(
clickX.toInt,
clickY.toInt,
70,
70
)
g2.setColor(
Color.WHITE
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
20
)
)
g2.drawString(
"CLICKS: " +
clicks +
" TIME: " +
secondsLeft,
20,
30
)
}
}
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
if (
e.getX >= clickX &&
e.getX <= clickX + 70 &&
e.getY >= clickY &&
e.getY <= clickY + 70
) {
clicks +=
1
clickX =
math.random *
math.max(
1,
panel.getWidth - 70
)
clickY =
60 +
math.random *
math.max(
1,
panel.getHeight - 130
)
panel.repaint()
}
}
}
)
val timer =
new Timer(
1000,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
secondsLeft -=
1
if (
secondsLeft <= 0
) {
secondsLeft =
20
clicks =
0
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// DODGE FIELD
// ============================================================
def launchDodgeField(): Unit = {
val gameFrame =
createGameFrame(
"DODGE FIELD - MOUSE"
)
var playerX =
420.0
var playerY =
500.0
val enemies =
ArrayBuffer[Point](
new Point(100,-50),
new Point(300,-180),
new Point(600,-100),
new Point(760,-240)
)
var dodgeScore =
0
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setColor(
new Color(
25,
25,
35
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
Color.CYAN
)
g2.fillOval(
playerX.toInt,
playerY.toInt,
50,
50
)
g2.setColor(
Color.RED
)
var i =
0
while (
i < enemies.length
) {
g2.fillRect(
enemies(i).x,
enemies(i).y,
45,
45
)
i +=
1
}
g2.setColor(
Color.WHITE
)
g2.drawString(
"SCORE: " +
dodgeScore,
20,
30
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
playerX =
math.max(
0,
math.min(
panel.getWidth - 50,
e.getX - 25
)
)
playerY =
math.max(
45,
math.min(
panel.getHeight - 50,
e.getY - 25
)
)
}
}
)
val timer =
new Timer(
30,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
var i =
0
while (
i < enemies.length
) {
enemies(i).y +=
5 +
i
if (
enemies(i).y >
panel.getHeight
) {
enemies(i).y =
-60
enemies(i).x =
(
math.random *
math.max(
1,
panel.getWidth - 45
)
).toInt
dodgeScore +=
1
}
val collision =
enemies(i).x + 45 >
playerX &&
enemies(i).x <
playerX + 50 &&
enemies(i).y + 45 >
playerY &&
enemies(i).y <
playerY + 50
if (
collision
) {
dodgeScore =
0
enemies(i).y =
-60
}
i +=
1
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// POTION ADVENTURE
// ============================================================
def launchPotionAdventure(): Unit = {
val gameFrame =
createGameFrame(
"POTION ADVENTURE - MOUSE"
)
var playerX =
80.0
var playerY =
470.0
var verticalVelocity =
0.0
var potionCollected =
false
var adventureWon =
false
val potion =
new java.awt.Rectangle(
350,
360,
40,
50
)
val goal =
new java.awt.Rectangle(
740,
120,
55,
55
)
val panel =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setPaint(
new GradientPaint(
0,
0,
new Color(
70,
175,
245
),
0,
getHeight,
new Color(
210,
240,
255
)
)
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
g2.setColor(
new Color(
65,
175,
75
)
)
g2.fillRect(
0,
getHeight - 100,
getWidth,
100
)
g2.setColor(
Color.BLUE
)
g2.fillRoundRect(
playerX.toInt,
playerY.toInt,
42,
58,
12,
12
)
if (
!potionCollected
) {
g2.setColor(
Color.RED
)
g2.fillRoundRect(
potion.x,
potion.y,
potion.width,
potion.height,
10,
10
)
}
if (
potionCollected
) {
g2.setColor(
Color.GREEN
)
g2.fillOval(
goal.x,
goal.y,
goal.width,
goal.height
)
}
g2.setColor(
Color.BLACK
)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
18
)
)
g2.drawString(
if (
adventureWon
)
"YOU WIN!"
else if (
potionCollected
)
"REACH THE GREEN GOAL"
else
"COLLECT THE RED POTION",
20,
30
)
}
}
panel.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseMoved(
e: MouseEvent
): Unit = {
playerX =
math.max(
0,
math.min(
panel.getWidth - 42,
e.getX - 21
)
)
}
}
)
panel.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
verticalVelocity =
-9
}
}
)
val timer =
new Timer(
30,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
verticalVelocity +=
0.45
playerY +=
verticalVelocity
val groundY =
panel.getHeight -
160
if (
playerY >
groundY
) {
playerY =
groundY
verticalVelocity =
0
}
val playerRectangle =
new java.awt.Rectangle(
playerX.toInt,
playerY.toInt,
42,
58
)
if (
!potionCollected &&
potion.intersects(
playerRectangle
)
) {
potionCollected =
true
}
if (
potionCollected &&
goal.intersects(
playerRectangle
)
) {
adventureWon =
true
}
panel.repaint()
}
}
)
timer.start()
gameFrame.addWindowListener(
new java.awt.event.WindowAdapter {
override def windowClosed(
e: java.awt.event.WindowEvent
): Unit = {
timer.stop()
}
}
)
gameFrame.add(
panel
)
gameFrame.setVisible(
true
)
}
// ============================================================
// GAME ROUTER
// ============================================================
def startSelectedGame(
name: String
): Unit = {
if (
name == "SLING BALL"
) {
launchSlingBall()
} else if (
name == "POTION ADVENTURE"
) {
launchPotionAdventure()
} else if (
name == "UNBEATABLE TIC TAC TOE"
) {
launchTicTacToe()
} else if (
name == "PONG"
) {
launchPong()
} else if (
name == "SNAKE"
) {
launchSnake()
} else if (
name == "BREAKOUT"
) {
launchBreakout()
} else if (
name == "FLAPPY BIRD"
) {
launchFlappy()
} else if (
name == "CAR DODGE"
) {
launchCarDodge()
} else if (
name == "SPACE SHOOTER"
) {
launchSpaceShooter()
} else if (
name == "TARGET SHOOTER"
) {
launchTargetShooter()
} else if (
name == "BALL CATCH"
) {
launchBallCatch()
} else if (
name == "BALL MAZE"
) {
launchBallMaze()
} else if (
name == "MEMORY MATCH"
) {
launchMemoryMatch()
} else if (
name == "CLICK RUSH"
) {
launchClickRush()
} else {
launchDodgeField()
}
}
// ============================================================
// GAME STUDIO
// ============================================================
def openGameStudio(): Unit = {
val gameFrame =
new JFrame(
"ULTRA LEGEND GAME STUDIO X8"
)
gameFrame.setDefaultCloseOperation(
WindowConstants.DISPOSE_ON_CLOSE
)
gameFrame.setSize(
1350,
820
)
gameFrame.setLocationRelativeTo(
mainFrame
)
val gameModel =
new DefaultListModel[String]()
var i =
0
while (
i < gameNames.length
) {
gameModel.addElement(
gameNames(i)
)
i += 1
}
val gameList =
new JList[String](
gameModel
)
gameList.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION
)
gameList.setFont(
new Font(
"Arial",
Font.BOLD,
15
)
)
val searchField =
new JTextField(
15
)
val searchButton =
createButton(
"SEARCH"
)
val createGameButton =
createButton(
"CREATE GAME"
)
val autoCreateButton =
createButton(
"AUTO CREATE"
)
val playButton =
createButton(
"PLAY"
)
val gameCodeButton =
createButton(
"GAME CODE"
)
val closeButton =
createButton(
"CLOSE"
)
val infoArea =
new JTextArea()
infoArea.setEditable(
false
)
infoArea.setFont(
new Font(
"Monospaced",
Font.PLAIN,
13
)
)
infoArea.setText(
"ULTRA GAME STUDIO X8\n\n" +
"15 READY GAMES\n\n" +
"DOUBLE CLICK = PLAY\n" +
"CREATE GAME = CREATE TEMPLATE\n" +
"AUTO CREATE = USE CURRENT DRAWING\n" +
"GAME CODE = GENERATE GAME SOURCE\n\n" +
"ALL GAME CONTROLS ARE MOUSE BASED."
)
val searchPanel =
new JPanel(
new FlowLayout(
FlowLayout.LEFT
)
)
searchPanel.add(
new JLabel(
"SEARCH:"
)
)
searchPanel.add(
searchField
)
searchPanel.add(
searchButton
)
val leftPanel =
new JPanel(
new BorderLayout()
)
leftPanel.add(
new JLabel(
"GAME LIBRARY"
),
BorderLayout.NORTH
)
leftPanel.add(
searchPanel,
BorderLayout.CENTER
)
leftPanel.add(
new JScrollPane(
gameList
),
BorderLayout.SOUTH
)
val rightPanel =
new JPanel(
new BorderLayout()
)
rightPanel.add(
new JLabel(
"CREATE GAME / INFORMATION"
),
BorderLayout.NORTH
)
rightPanel.add(
new JScrollPane(
infoArea
),
BorderLayout.CENTER
)
val split =
new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
leftPanel,
rightPanel
)
split.setDividerLocation(
420
)
split.setResizeWeight(
0.30
)
gameList.addListSelectionListener(
new javax.swing.event.ListSelectionListener {
override def valueChanged(
e: javax.swing.event.ListSelectionEvent
): Unit = {
if (
!e.getValueIsAdjusting
) {
val selectedGame =
gameList.getSelectedValue
if (
selectedGame != null
) {
var description =
""
var j =
0
while (
j < gameNames.length
) {
if (
gameNames(j) ==
selectedGame
) {
description =
gameDescriptions(j)
}
j += 1
}
infoArea.setText(
"GAME\n\n" +
selectedGame +
"\n\n" +
description +
"\n\n" +
"MOUSE CONTROLLED\n\n" +
"Press PLAY to start."
)
}
}
}
}
)
searchButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val query =
searchField
.getText
.trim
.toLowerCase
gameModel.clear()
var j =
0
while (
j < gameNames.length
) {
if (
query.isEmpty ||
gameNames(j)
.toLowerCase
.indexOf(query) >= 0
) {
gameModel.addElement(
gameNames(j)
)
}
j += 1
}
}
}
)
playButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val selectedGame =
gameList.getSelectedValue
if (
selectedGame != null
) {
startSelectedGame(
selectedGame
)
} else {
JOptionPane.showMessageDialog(
gameFrame,
"SELECT A GAME FIRST."
)
}
}
}
)
gameList.addMouseListener(
new MouseAdapter {
override def mouseClicked(
e: MouseEvent
): Unit = {
if (
e.getClickCount == 2
) {
val selectedGame =
gameList.getSelectedValue
if (
selectedGame != null
) {
startSelectedGame(
selectedGame
)
}
}
}
}
)
createGameButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val selectedGame =
gameList.getSelectedValue
if (
selectedGame != null
) {
generatedGameCode =
createGameSource(
selectedGame
)
infoArea.setText(
"GAME CREATED\n\n" +
selectedGame +
"\n\n" +
"Template created successfully.\n" +
"Press PLAY to start.\n" +
"Press GAME CODE to inspect the source."
)
} else {
infoArea.setText(
"SELECT A GAME FIRST."
)
}
}
}
)
autoCreateButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val detectedGame =
autoGameFromDrawing()
gameList.setSelectedValue(
detectedGame,
true
)
generatedGameCode =
createGameSource(
detectedGame
)
infoArea.setText(
"AUTO CREATE COMPLETE\n\n" +
"DRAWING / OBJECT:\n" +
"Mapped to:\n\n" +
detectedGame +
"\n\n" +
"Press PLAY to start."
)
}
}
)
gameCodeButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val selectedGame =
gameList.getSelectedValue
if (
selectedGame != null
) {
generatedGameCode =
createGameSource(
selectedGame
)
val codeFrame =
new JFrame(
"GAME CODE"
)
codeFrame.setDefaultCloseOperation(
WindowConstants.DISPOSE_ON_CLOSE
)
codeFrame.setSize(
900,
650
)
codeFrame.setLocationRelativeTo(
gameFrame
)
val area =
new JTextArea()
area.setFont(
new Font(
"Monospaced",
Font.PLAIN,
13
)
)
area.setText(
generatedGameCode
)
val copyButton =
createButton(
"COPY CODE"
)
copyButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
copyGeneratedText(
area.getText
)
}
}
)
codeFrame.setLayout(
new BorderLayout()
)
codeFrame.add(
new JScrollPane(
area
),
BorderLayout.CENTER
)
codeFrame.add(
copyButton,
BorderLayout.SOUTH
)
codeFrame.setVisible(
true
)
} else {
JOptionPane.showMessageDialog(
gameFrame,
"SELECT A GAME FIRST."
)
}
}
}
)
closeButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
gameFrame.dispose()
}
}
)
val bottomPanel =
new JPanel(
new FlowLayout(
FlowLayout.CENTER
)
)
bottomPanel.add(
createGameButton
)
bottomPanel.add(
autoCreateButton
)
bottomPanel.add(
playButton
)
bottomPanel.add(
gameCodeButton
)
bottomPanel.add(
closeButton
)
gameFrame.setLayout(
new BorderLayout()
)
gameFrame.add(
split,
BorderLayout.CENTER
)
gameFrame.add(
bottomPanel,
BorderLayout.SOUTH
)
gameFrame.setVisible(
true
)
}
// ============================================================
// MAIN DRAWING CANVAS
// ============================================================
drawingCanvas =
new JPanel {
override def paintComponent(
graphics: Graphics
): Unit = {
super.paintComponent(
graphics
)
val g2 =
graphics.asInstanceOf[
Graphics2D
]
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
g2.setColor(
Color.WHITE
)
g2.fillRect(
0,
0,
getWidth,
getHeight
)
// GRID
if (
gridEnabled
) {
g2.setColor(
new Color(
0,
0,
0,
20
)
)
var x =
0
while (
x <= CANVAS_WIDTH
) {
g2.drawLine(
x,
0,
x,
CANVAS_HEIGHT
)
x +=
50
}
var y =
0
while (
y <= CANVAS_HEIGHT
) {
g2.drawLine(
0,
y,
CANVAS_WIDTH,
y
)
y +=
50
}
}
// DRAW OBJECTS
var i =
0
while (
i < drawItems.length
) {
val item =
drawItems(i)
if (
item.visible &&
item.points.length >= 2
) {
if (
item.filled &&
item.points.length >= 3
) {
val path =
new java.awt.geom.Path2D.Double()
path.moveTo(
item.points.head.x,
item.points.head.y
)
var j =
1
while (
j < item.points.length
) {
path.lineTo(
item.points(j).x,
item.points(j).y
)
j += 1
}
path.closePath()
g2.setColor(
item.fillColor
)
g2.fill(
path
)
}
g2.setColor(
item.strokeColor
)
g2.setStroke(
new BasicStroke(
brushWidth,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
var j =
1
while (
j < item.points.length
) {
g2.drawLine(
item.points(j - 1).x,
item.points(j - 1).y,
item.points(j).x,
item.points(j).y
)
j +=
1
}
}
i +=
1
}
// TEMPORARY FREEHAND
if (
temporaryPoints.length >= 2
) {
g2.setColor(
currentStrokeColor
)
g2.setStroke(
new BasicStroke(
brushWidth,
BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND
)
)
var j =
1
while (
j < temporaryPoints.length
) {
g2.drawLine(
temporaryPoints(j - 1).x,
temporaryPoints(j - 1).y,
temporaryPoints(j).x,
temporaryPoints(j).y
)
j +=
1
}
}
// SELECTION
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length &&
currentTool == "SELECT"
) {
val bounds =
itemBounds(
drawItems(
selectedItemIndex
)
)
val selectionRect =
new java.awt.Rectangle(
bounds.x - 8,
bounds.y - 8,
bounds.width + 16,
bounds.height + 16
)
g2.setColor(
new Color(
0,
105,
240
)
)
g2.setStroke(
new BasicStroke(
2
)
)
g2.drawRect(
selectionRect.x,
selectionRect.y,
selectionRect.width,
selectionRect.height
)
val hs =
selectionHandles(
selectionRect
)
var h =
0
while (
h < hs.length
) {
val handlePoint =
hs(h)._2
g2.setColor(
Color.WHITE
)
g2.fillRect(
handlePoint.x - 5,
handlePoint.y - 5,
10,
10
)
g2.setColor(
new Color(
0,
105,
240
)
)
g2.drawRect(
handlePoint.x - 5,
handlePoint.y - 5,
10,
10
)
h +=
1
}
}
}
}
// ============================================================
// CANVAS MOUSE INPUT
// ============================================================
drawingCanvas.addMouseListener(
new MouseAdapter {
override def mousePressed(
e: MouseEvent
): Unit = {
val p =
canvasPoint(e)
if (
currentTool ==
"SELECT"
) {
val hit =
findItemAt(p)
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length
) {
val handle =
findResizeHandle(
drawItems(
selectedItemIndex
),
p
)
if (
handle != ""
) {
if (
!drawItems(
selectedItemIndex
).locked
) {
saveHistory()
resizingSelected =
true
movingSelected =
false
resizeMode =
handle
originalSelectedPoints =
drawItems(
selectedItemIndex
).points
previousMousePoint =
p
}
} else if (
hit ==
selectedItemIndex
) {
if (
!drawItems(
selectedItemIndex
).locked
) {
saveHistory()
movingSelected =
true
resizingSelected =
false
previousMousePoint =
p
}
} else {
selectedItemIndex =
hit
}
} else {
selectedItemIndex =
hit
}
repaintDrawingCanvas()
} else if (
currentTool ==
"BUCKET"
) {
val hit =
findItemAt(p)
if (
hit >= 0
) {
selectedItemIndex =
hit
bucketFillSelected()
} else {
setMainStatus(
"SELECT A CLOSED OBJECT"
)
}
} else if (
currentTool ==
"ERASER"
) {
val hit =
findItemAt(p)
if (
hit >= 0 &&
!drawItems(hit).locked
) {
saveHistory()
drawItems.remove(hit)
selectedItemIndex =
-1
repaintDrawingCanvas()
setMainStatus(
"OBJECT ERASED"
)
}
} else {
saveHistory()
temporaryPoints.clear()
temporaryPoints +=
p
drawingActive =
true
selectedItemIndex =
-1
setMainStatus(
"DRAWING..."
)
}
}
override def mouseReleased(
e: MouseEvent
): Unit = {
if (
currentTool ==
"SELECT"
) {
movingSelected =
false
resizingSelected =
false
repaintDrawingCanvas()
} else if (
drawingActive
) {
temporaryPoints +=
canvasPoint(e)
if (
temporaryPoints.length >= 2
) {
drawItems +=
DrawItem(
temporaryPoints.toVector,
currentStrokeColor,
currentFillColor,
isClosedShape(
temporaryPoints
),
"FREEHAND",
true,
false
)
selectedItemIndex =
drawItems.length - 1
}
temporaryPoints.clear()
drawingActive =
false
repaintDrawingCanvas()
setMainStatus(
"DRAWING RECORDED"
)
}
}
}
)
// ============================================================
// CANVAS DRAGGING
// ============================================================
drawingCanvas.addMouseMotionListener(
new MouseMotionAdapter {
override def mouseDragged(
e: MouseEvent
): Unit = {
val p =
canvasPoint(e)
if (
currentTool ==
"SELECT"
) {
if (
movingSelected &&
selectedItemIndex >= 0
) {
moveSelectedItem(
p.x -
previousMousePoint.x,
p.y -
previousMousePoint.y
)
previousMousePoint =
p
repaintDrawingCanvas()
} else if (
resizingSelected &&
selectedItemIndex >= 0
) {
resizeSelectedItem(
p
)
repaintDrawingCanvas()
}
} else if (
drawingActive
) {
if (
temporaryPoints.isEmpty ||
pointDistance(
temporaryPoints.last,
p
) >= 2
) {
temporaryPoints +=
p
repaintDrawingCanvas()
}
}
}
}
)
// ============================================================
// MAIN BUTTONS
// ============================================================
val pencilButton =
createButton(
"PENCIL"
)
val selectButton =
createButton(
"SELECT"
)
val eraserButton =
createButton(
"ERASER"
)
val bucketButton =
createButton(
"BUCKET"
)
val undoButton =
createButton(
"UNDO"
)
val redoButton =
createButton(
"REDO"
)
val clearButton =
createButton(
"CLEAR"
)
val generateCodeButton =
createButton(
"DRAW CODE"
)
val copyCodeButton =
createButton(
"COPY"
)
val saveCodeButton =
createButton(
"SAVE CODE"
)
val openGamesButton =
createButton(
"GAMES"
)
val gridButton =
createButton(
"GRID"
)
val snapButton =
createButton(
"SNAP"
)
val strokeColorButton =
createButton(
"STROKE"
)
val fillColorButton =
createButton(
"FILL"
)
// ============================================================
// TOOLBAR
// ============================================================
val mainToolbar =
new JPanel(
new FlowLayout(
FlowLayout.LEFT,
3,
3
)
)
mainToolbar.add(
pencilButton
)
mainToolbar.add(
selectButton
)
mainToolbar.add(
eraserButton
)
mainToolbar.add(
bucketButton
)
mainToolbar.add(
undoButton
)
mainToolbar.add(
redoButton
)
mainToolbar.add(
clearButton
)
mainToolbar.add(
generateCodeButton
)
mainToolbar.add(
copyCodeButton
)
mainToolbar.add(
saveCodeButton
)
mainToolbar.add(
openGamesButton
)
mainToolbar.add(
gridButton
)
mainToolbar.add(
snapButton
)
mainToolbar.add(
strokeColorButton
)
mainToolbar.add(
fillColorButton
)
// ============================================================
// OBJECT / SHAPE UI
// ============================================================
objectList =
new JList[String](
objectModel
)
objectList.setFont(
new Font(
"Arial",
Font.BOLD,
13
)
)
shapeList =
new JList[String](
shapeModel
)
shapeList.setFont(
new Font(
"Arial",
Font.BOLD,
13
)
)
objectSearchField =
new JTextField(
12
)
val objectSearchButton =
createButton(
"SEARCH"
)
val objectSearchPanel =
new JPanel(
new FlowLayout(
FlowLayout.LEFT
)
)
objectSearchPanel.add(
objectSearchField
)
objectSearchPanel.add(
objectSearchButton
)
val objectPanel =
new JPanel(
new BorderLayout()
)
objectPanel.add(
new JLabel(
"OBJECT LIBRARY - DOUBLE CLICK"
),
BorderLayout.NORTH
)
objectPanel.add(
objectSearchPanel,
BorderLayout.CENTER
)
objectPanel.add(
new JScrollPane(
objectList
),
BorderLayout.SOUTH
)
val shapePanel =
new JPanel(
new BorderLayout()
)
shapePanel.add(
new JLabel(
"SHAPE LIBRARY - DOUBLE CLICK"
),
BorderLayout.NORTH
)
shapePanel.add(
new JScrollPane(
shapeList
),
BorderLayout.CENTER
)
val libraryTabs =
new JTabbedPane()
libraryTabs.addTab(
"OBJECTS",
objectPanel
)
libraryTabs.addTab(
"SHAPES",
shapePanel
)
// ============================================================
// SEARCH
// ============================================================
objectSearchButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val query =
objectSearchField
.getText
.trim
.toLowerCase
objectModel.clear()
var i =
0
while (
i < allObjectNames.length
) {
if (
query.isEmpty ||
allObjectNames(i)
.toLowerCase
.indexOf(query) >= 0
) {
objectModel.addElement(
allObjectNames(i)
)
}
i +=
1
}
}
}
)
// ============================================================
// OBJECT DOUBLE CLICK
// ============================================================
objectList.addMouseListener(
new MouseAdapter {
override def mouseClicked(
e: MouseEvent
): Unit = {
if (
e.getClickCount == 2
) {
val value =
objectList.getSelectedValue
if (
value != null
) {
addObjectToCanvas(
value
)
}
}
}
}
)
// ============================================================
// SHAPE DOUBLE CLICK
// ============================================================
shapeList.addMouseListener(
new MouseAdapter {
override def mouseClicked(
e: MouseEvent
): Unit = {
if (
e.getClickCount == 2
) {
val value =
shapeList.getSelectedValue
if (
value != null
) {
addShapeToCanvas(
value
)
}
}
}
}
)
// ============================================================
// CODE AREA
// ============================================================
drawingCodeArea =
new JTextArea()
drawingCodeArea.setEditable(
false
)
drawingCodeArea.setFont(
new Font(
"Monospaced",
Font.PLAIN,
13
)
)
drawingCodeArea.setText(
"// DRAW SOMETHING\n" +
"// THEN PRESS DRAW CODE"
)
// ============================================================
// PANELS
// ============================================================
val canvasPanel =
new JPanel(
new BorderLayout()
)
canvasPanel.add(
new JLabel(
"DRAWING CANVAS"
),
BorderLayout.NORTH
)
canvasPanel.add(
drawingCanvas,
BorderLayout.CENTER
)
val codePanel =
new JPanel(
new BorderLayout()
)
codePanel.add(
new JLabel(
"GENERATED KOJO / SCALA CODE"
),
BorderLayout.NORTH
)
codePanel.add(
new JScrollPane(
drawingCodeArea
),
BorderLayout.CENTER
)
val canvasCodeSplit =
new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
canvasPanel,
codePanel
)
canvasCodeSplit.setDividerLocation(
660
)
canvasCodeSplit.setResizeWeight(
0.62
)
val mainSplit =
new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
libraryTabs,
canvasCodeSplit
)
mainSplit.setDividerLocation(
275
)
mainSplit.setResizeWeight(
0.0
)
// ============================================================
// STATUS
// ============================================================
mainStatus =
new JLabel(
"ULTRA LEGEND X8 READY"
)
mainStatus.setFont(
new Font(
"Arial",
Font.BOLD,
13
)
)
// ============================================================
// MAIN FRAME
// ============================================================
mainFrame =
new JFrame(
"ULTRA LEGEND DRAW + GAME STUDIO X8"
)
mainFrame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE
)
mainFrame.setSize(
1700,
920
)
mainFrame.setMinimumSize(
new Dimension(
1100,
650
)
)
mainFrame.setLocationRelativeTo(
null
)
mainFrame.setLayout(
new BorderLayout(
4,
4
)
)
mainFrame.add(
mainToolbar,
BorderLayout.NORTH
)
mainFrame.add(
mainSplit,
BorderLayout.CENTER
)
mainFrame.add(
mainStatus,
BorderLayout.SOUTH
)
// ============================================================
// TOOL ACTIONS
// ============================================================
pencilButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
currentTool =
"PENCIL"
selectedItemIndex =
-1
drawingCanvas.setCursor(
Cursor.getPredefinedCursor(
Cursor.CROSSHAIR_CURSOR
)
)
setMainStatus(
"PENCIL MODE"
)
drawingCanvas.requestFocusInWindow()
}
}
)
selectButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
currentTool =
"SELECT"
drawingCanvas.setCursor(
Cursor.getPredefinedCursor(
Cursor.DEFAULT_CURSOR
)
)
setMainStatus(
"SELECT / MOVE / RESIZE"
)
repaintDrawingCanvas()
drawingCanvas.requestFocusInWindow()
}
}
)
eraserButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
currentTool =
"ERASER"
selectedItemIndex =
-1
drawingCanvas.setCursor(
Cursor.getPredefinedCursor(
Cursor.CROSSHAIR_CURSOR
)
)
setMainStatus(
"ERASER MODE"
)
drawingCanvas.requestFocusInWindow()
}
}
)
bucketButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
currentTool =
"BUCKET"
drawingCanvas.setCursor(
Cursor.getPredefinedCursor(
Cursor.HAND_CURSOR
)
)
setMainStatus(
"BUCKET MODE"
)
drawingCanvas.requestFocusInWindow()
}
}
)
undoButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
performUndo()
}
}
)
redoButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
performRedo()
}
}
)
clearButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
clearDrawing()
}
}
)
generateCodeButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
generateDrawingCode()
}
}
)
copyCodeButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
copyGeneratedText(
drawingCodeArea.getText
)
}
}
)
saveCodeButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
saveGeneratedText(
drawingCodeArea.getText
)
}
}
)
openGamesButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
openGameStudio()
}
}
)
gridButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
gridEnabled =
!gridEnabled
repaintDrawingCanvas()
setMainStatus(
if (
gridEnabled
)
"GRID ON"
else
"GRID OFF"
)
}
}
)
snapButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
snapEnabled =
!snapEnabled
setMainStatus(
if (
snapEnabled
)
"SNAP ON"
else
"SNAP OFF"
)
}
}
)
strokeColorButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val chosenColor =
JColorChooser.showDialog(
mainFrame,
"CHOOSE STROKE COLOR",
currentStrokeColor
)
if (
chosenColor != null
) {
currentStrokeColor =
chosenColor
setMainStatus(
"STROKE COLOR SELECTED"
)
}
}
}
)
fillColorButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val chosenColor =
JColorChooser.showDialog(
mainFrame,
"CHOOSE FILL COLOR",
currentFillColor
)
if (
chosenColor != null
) {
currentFillColor =
chosenColor
if (
selectedItemIndex >= 0
) {
bucketFillSelected()
} else {
setMainStatus(
"FILL COLOR SELECTED"
)
}
}
}
}
)
// ============================================================
// KEYBOARD SHORTCUTS
// ============================================================
drawingCanvas.addKeyListener(
new java.awt.event.KeyAdapter {
override def keyPressed(
e: java.awt.event.KeyEvent
): Unit = {
val code =
e.getKeyCode
if (
e.isControlDown &&
code ==
java.awt.event.KeyEvent.VK_Z
) {
performUndo()
} else if (
e.isControlDown &&
code ==
java.awt.event.KeyEvent.VK_Y
) {
performRedo()
} else if (
e.isControlDown &&
code ==
java.awt.event.KeyEvent.VK_G
) {
generateDrawingCode()
} else if (
e.isControlDown &&
code ==
java.awt.event.KeyEvent.VK_C
) {
copyGeneratedText(
drawingCodeArea.getText
)
} else if (
e.isControlDown &&
code ==
java.awt.event.KeyEvent.VK_S
) {
saveGeneratedText(
drawingCodeArea.getText
)
} else if (
e.isControlDown &&
code ==
java.awt.event.KeyEvent.VK_D
) {
openGameStudio()
} else if (
code ==
java.awt.event.KeyEvent.VK_DELETE
) {
if (
selectedItemIndex >= 0 &&
selectedItemIndex < drawItems.length
) {
saveHistory()
drawItems.remove(
selectedItemIndex
)
selectedItemIndex =
-1
repaintDrawingCanvas()
setMainStatus(
"SELECTED OBJECT DELETED"
)
}
} else if (
code ==
java.awt.event.KeyEvent.VK_P
) {
currentTool =
"PENCIL"
setMainStatus(
"PENCIL"
)
} else if (
code ==
java.awt.event.KeyEvent.VK_V
) {
currentTool =
"SELECT"
setMainStatus(
"SELECT"
)
} else if (
code ==
java.awt.event.KeyEvent.VK_B
) {
currentTool =
"BUCKET"
setMainStatus(
"BUCKET"
)
} else if (
code ==
java.awt.event.KeyEvent.VK_E
) {
currentTool =
"ERASER"
setMainStatus(
"ERASER"
)
} else if (
code ==
java.awt.event.KeyEvent.VK_F1
) {
JOptionPane.showMessageDialog(
mainFrame,
"ULTRA X8 SHORTCUTS\n\n" +
"P = PENCIL\n" +
"V = SELECT\n" +
"B = BUCKET\n" +
"E = ERASER\n" +
"DELETE = DELETE OBJECT\n\n" +
"CTRL+Z = UNDO\n" +
"CTRL+Y = REDO\n" +
"CTRL+G = DRAW CODE\n" +
"CTRL+C = COPY CODE\n" +
"CTRL+S = SAVE CODE\n" +
"CTRL+D = GAME STUDIO\n\n" +
"SELECT + DRAG = MOVE\n" +
"SELECT + HANDLE = RESIZE",
"ULTRA SHORTCUT CENTER",
JOptionPane.INFORMATION_MESSAGE
)
}
}
}
)
// ============================================================
// START
// ============================================================
SwingUtilities.invokeLater(
new Runnable {
override def run(): Unit = {
mainFrame.setVisible(
true
)
drawingCanvas.requestFocusInWindow()
setMainStatus(
"ULTRA LEGEND X8 READY"
)
}
}
)