Skip to content

Instantly share code, notes, and snippets.

@danirod
Last active September 16, 2022 20:39
Show Gist options
  • Save danirod/c839764e1490cd16f4f59c3209d851e5 to your computer and use it in GitHub Desktop.
Save danirod/c839764e1490cd16f4f59c3209d851e5 to your computer and use it in GitHub Desktop.

Revisions

  1. danirod revised this gist Sep 16, 2022. No changes.
  2. danirod created this gist Sep 16, 2022.
    303 changes: 303 additions & 0 deletions pacman.groovy
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,303 @@
    import javax.swing.*
    import java.awt.Color
    import java.awt.Graphics
    import java.awt.Graphics2D
    import java.awt.event.*

    class Fantasmita {

    public int posx, posy
    public int dx, dy
    Pacman pacman

    Fantasmita(int posx, int posy, Pacman pacman) {
    this.posx = posx
    this.posy = posy
    this.pacman = pacman
    updateLook()
    }

    private updateLook() {
    int pdx, pdy
    switch (Math.random()) {
    case { it <= 0.25 }:
    pdx = 1
    pdy = 0
    break
    case { it <= 0.5 }:
    pdx = -1
    pdy = 0
    break
    case { it <= 0.75 }:
    pdx = 0
    pdy = 1
    break
    default:
    pdx = 0
    pdy = -1
    break
    }

    if (dx == 0 && dy == 0) {
    dx = pdx
    dy = pdy
    return
    }

    // Check if we already looking wall
    int nextx = (this.posx + dx) % 10
    int nexty = (this.posy + dy) % 10
    while (nextx < 0) nextx += 10
    while (nexty < 0) nexty += 10
    boolean lookingWall = this.pacman.map[nextx][nexty]

    // Check if the ghost would look at a free cell on turn
    int posiblex = (this.posx + pdx) % 10
    int posibley = (this.posy + pdy) % 10
    while (posiblex < 0) posiblex += 10
    while (posibley < 0) posibley += 10
    if (!this.pacman.map[posiblex][posibley]) {
    // You can only turn 180 if it is a wall
    boolean is180 = (dx == pdx && dy != pdy) || (dx != pdx && dy == pdy)
    if (lookingWall || !is180) {
    dx = pdx
    dy = pdy
    }
    } else {
    updateLook()
    }
    }

    void draw(Graphics2D g) {
    g.setPaint(Color.red)
    g.fillArc(50 * posx + 10, 50 * posy + 10, 30, 30, 0, 360)
    }

    void update() {
    updateLook()
    int nextx = (this.posx + this.dx) % 10
    int nexty = (this.posy + this.dy) % 10
    while (nextx < 0) nextx += 10
    while (nexty < 0) nexty += 10
    if (!this.pacman.map[nextx][nexty]) {
    this.posx = nextx
    this.posy = nexty
    }
    }
    }

    class Pacman extends JPanel implements ActionListener, KeyListener {
    static boolean OCUPADO = true
    static boolean LIBRE = false

    boolean[][] ocupado
    boolean[][] monedicas
    int posx = 5, posy = 5, dx = 1, dy = 0
    Timer timer
    Fantasmita fanta

    boolean moverse = false
    boolean updatable = true
    boolean lose = false

    Pacman() {
    this.ocupado = generarLaberinto(10, 10)
    this.monedicas = generarMonedicas(10, 10, this.ocupado)

    var (fantax, fantay) = nextFree()
    this.fanta = new Fantasmita(fantax, fantay, this)

    timer = new Timer(250, this)
    timer.start()
    }

    private int[] nextFree() {
    int px, py
    do {
    px = Math.random() * this.ocupado[0].length
    py = Math.random() * this.ocupado.length
    } while (this.ocupado[px][py])
    [px, py]
    }

    boolean[][] getMap() {
    return ocupado
    }

    private boolean[][] generarLaberinto(int w, int h) {
    boolean[][] lab = new boolean[w][h]
    (1..50).each { ite ->
    int px, py
    do {
    px = Math.random() * w
    py = Math.random() * h
    } while (lab[px][py])
    lab[px][py] = OCUPADO
    }
    lab[this.posx][this.posy] = LIBRE
    return lab
    }

    private boolean[][] generarMonedicas(int w, int h, boolean[][] unavail) {
    boolean[][] lab = new boolean[w][h]
    (1..20).each { ite ->
    int px, py
    do {
    px = Math.random() * w
    py = Math.random() * h
    } while (unavail[px][py] && lab[px][py])
    lab[px][py] = OCUPADO
    }
    return lab
    }

    @Override
    public void paintComponent(Graphics g) {
    super.paintComponent(g)
    dibujar(g as Graphics2D)
    }

    private dibujar(Graphics2D g) {
    g.setPaint(Color.black)
    g.fillRect(0, 0, getWidth(), getHeight())

    g.setPaint(Color.white)
    (0..<10).each { y ->
    (0..<10).each { x ->
    boolean ocupee = this.ocupado[x][y]
    g.drawRect(50 * x, 50 * y, 50, 50)
    if (ocupee) {
    g.fillRect(50 * x, 50 * y, 50, 50)
    }
    }
    }

    g.setPaint(Color.white)
    (0..<10).each { y ->
    (0..<10).each { x ->
    boolean monedica = this.monedicas[x][y]
    if (monedica) {
    g.fillArc(50 * x + 20, 50 * y + 20, 10, 10, 0, 360)
    }
    }
    }

    g.setPaint(Color.yellow)
    if (!moverse)
    g.fillArc(50 * posx, 50 * posy, 50, 50, angle(), 300)
    else
    g.fillArc(50 * posx, 50 * posy, 50, 50, 0, 360)

    fanta.draw(g)

    if (!updatable) {
    if (lose) {
    g.setPaint(Color.red)
    g.drawString("YOU LOSE", 50, 550)
    } else {
    g.setPaint(Color.green)
    g.drawString("YOU WIN", 50, 550)
    }
    }
    }

    private int angle() {
    if (dx == 1) {
    return 30
    } else if (dx == -1) {
    return 30 + 180
    } else if (dy == 1) {
    return 120 + 180
    } else if (dy == -1) {
    return 120
    }
    }

    private void move() {
    int nposx = (posx + dx) % 10
    int nposy = (posy + dy) % 10
    while (nposx < 0) nposx += 10
    while (nposy < 0) nposy += 10
    if (!ocupado[nposx][nposy]) {
    posx = nposx
    posy = nposy
    }
    if (monedicas[posx][posy]) {
    monedicas[posx][posy] = false
    }
    }

    private int monedasPendientes() {
    int monedas = 0
    (0..<10).each { x ->
    (0..<10).each { y ->
    if (monedicas[x][y])
    monedas++
    }
    }
    monedas
    }

    @Override
    public void actionPerformed(ActionEvent e) {
    if (!updatable)
    return
    moverse = !moverse
    if (moverse) {
    move()
    fanta.update()

    if (fanta.posx == this.posx && fanta.posy == this.posy) {
    updatable = false
    lose = true
    }
    if (monedasPendientes() == 0) {
    updatable = false
    lose = false
    }
    }
    repaint()
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
    switch (e.keyCode) {
    case 38: // ARRIBA
    dx = 0
    dy = -1
    break
    case 39: // DERECHA
    dx = 1
    dy = 0
    break
    case 40: // ABAJO
    dx =0
    dy =1
    break
    case 37: // IZQUIERDA
    dx = -1
    dy = 0
    break
    }
    repaint()
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
    }

    pacman = new Pacman()
    JFrame frame = new JFrame()
    frame.title = "Hola mundo"
    frame.setSize(640, 640)
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
    frame.add(pacman)
    frame.addKeyListener(pacman)
    frame.setVisible(true)