Skip to content

Commit 902ccaa

Browse files
author
Martin Doyen
committed
[IMP] awesome_clicker: Add BigBots
Chapter 11 of tutorial "Master the web framework" > "Chapter 1: Build a Clicker Game"
1 parent b32f7d8 commit 902ccaa

File tree

9 files changed

+213
-0
lines changed

9 files changed

+213
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Component, useState } from "@odoo/owl";
2+
import { registry } from "@web/core/registry";
3+
import { useClicker } from "../clicker_hook";
4+
import { ClickerValue } from "../clicker_value/clicker_value";
5+
6+
class ClickerClientAction extends Component {
7+
static template = "awesome_clicker.ClickerClientAction";
8+
static components = { ClickerValue };
9+
10+
setup() {
11+
this.clickerService = useClicker();
12+
}
13+
}
14+
15+
registry.category("actions").add("awesome_clicker.clicker_client_action", ClickerClientAction);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_clicker.ClickerClientAction">
4+
<span class="me-2">
5+
Clicks: <ClickerValue />
6+
</span>
7+
<button class="btn btn-primary" t-on-click="() => clickerService.increment(500)">Increment</button>
8+
<h3>Bots</h3>
9+
<div class="d-flex flex-row">
10+
<div class="card">
11+
<div t-if="clickerService.bots.clickBot.purchased">
12+
<div class="card-header">
13+
<t t-esc="clickerService.bots.clickBot.purchased" />x ClickBots (10 clicks/10 seconds)
14+
<i class="fa fa-android"></i>
15+
</div>
16+
</div>
17+
<div class="card-body">
18+
<button class="btn btn-primary" t-on-click="() => clickerService.buyBot('clickBot')" t-att-disabled="clickerService.clicks lt 1000">Buy ClickBot (1000 clicks)</button>
19+
</div>
20+
</div>
21+
22+
<div class="card" t-if="clickerService.level gte 2">
23+
<div t-if="clickerService.bots.bigBot.purchased">
24+
<div class="card-header">
25+
<t t-esc="clickerService.bots.bigBot.purchased" />x bigBots (100 clicks/10 seconds)
26+
<i class="fa fa-android"></i>
27+
</div>
28+
</div>
29+
<div class="card-body">
30+
<button class="btn btn-primary" t-on-click="() => clickerService.buyBot('bigBot')" t-att-disabled="clickerService.clicks lt 5000">Buy BigBot (5000 clicks)</button>
31+
</div>
32+
</div>
33+
</div>
34+
</t>
35+
</templates>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { useState } from "@odoo/owl";
2+
import { useService } from "@web/core/utils/hooks";
3+
4+
export function useClicker() {
5+
return useState(useService("awesome_clicker.count"));
6+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { registry } from "@web/core/registry";
2+
import { ClickerModel } from "./model/clicker_model";
3+
4+
export const getCount = {
5+
dependencies: ["effect"],
6+
start(env, services) {
7+
const clicker = new ClickerModel();
8+
9+
setInterval(() => {
10+
clicker.tick();
11+
}, 10000)
12+
13+
const bus = clicker.bus
14+
bus.addEventListener("MILESTONE", (ev) => {
15+
services.effect.add({
16+
message: `Milestone reached! You can now buy ${ev.detail}!`,
17+
type: "rainbow_man",
18+
})
19+
})
20+
21+
document.addEventListener("click", () => clicker.increment(1), true)
22+
23+
return clicker;
24+
}
25+
}
26+
27+
registry.category("services").add("awesome_clicker.count", getCount);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { registry } from "@web/core/registry";
2+
import { Component } from "@odoo/owl";
3+
import { useService } from "@web/core/utils/hooks";
4+
import { useClicker } from "../clicker_hook";
5+
import { ClickerValue } from "../clicker_value/clicker_value";
6+
7+
export class ClickerSystray extends Component {
8+
static template = "awesome_clicker.ClickerSystray";
9+
static components = { ClickerValue };
10+
11+
setup() {
12+
this.counterService = useClicker();
13+
this.action = useService("action");
14+
}
15+
16+
openClientAction() {
17+
this.action.doAction({
18+
type: "ir.actions.client",
19+
tag: "awesome_clicker.clicker_client_action",
20+
target: "new",
21+
name: "Clicker Game",
22+
})
23+
}
24+
}
25+
26+
export const systrayItem = {
27+
Component: ClickerSystray,
28+
};
29+
30+
registry.category("systray").add("awesome_clicker.ClickerSystray", systrayItem, { sequence: 1000 });
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_clicker.ClickerSystray">
4+
<div class="o_nav_entry">
5+
<div class="me-2">
6+
Clicks: <ClickerValue />
7+
</div>
8+
<button class="btn btn-secondary me-2" t-on-click="() => this.counterService.increment(9)">
9+
<i class="fa fa-lg fa-plus"></i>
10+
</button>
11+
<button class="btn btn-secondary" t-on-click="openClientAction">
12+
Open
13+
</button>
14+
</div>
15+
</t>
16+
</templates>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Component } from "@odoo/owl";
2+
import { useClicker } from "../clicker_hook";
3+
import { humanNumber } from "@web/core/utils/numbers";
4+
5+
export class ClickerValue extends Component {
6+
static template = "awesome_clicker.ClickerValue";
7+
8+
setup() {
9+
this.clicker = useClicker();
10+
}
11+
12+
get getClicks() {
13+
return humanNumber(this.clicker.clicks, {
14+
decimals: 1,
15+
});
16+
}
17+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates xml:space="preserve">
3+
<t t-name="awesome_clicker.ClickerValue">
4+
<span t-esc="getClicks" t-att-data-tooltip="clicker.clicks" />
5+
</t>
6+
</templates>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { Reactive } from "@web/core/utils/reactive";
2+
import { EventBus } from "@odoo/owl";
3+
4+
export class ClickerModel extends Reactive {
5+
6+
constructor() {
7+
super();
8+
this.clicks = 0;
9+
this.level = 0;
10+
this.bus = new EventBus();
11+
this.bots = {
12+
clickBot: {
13+
price: 1000,
14+
level: 1,
15+
increment: 10,
16+
purchased: 0,
17+
},
18+
bigBot: {
19+
price: 5000,
20+
level: 2,
21+
increment: 100,
22+
purchased: 0,
23+
},
24+
}
25+
}
26+
27+
increment(value) {
28+
this.clicks += value;
29+
30+
if (this.milestones[this.level] && this.clicks >= this.milestones[this.level].clicks) {
31+
this.bus.trigger("MILESTONE", this.milestones[this.level].unlock);
32+
this.level++;
33+
}
34+
}
35+
36+
buyBot(name) {
37+
if (!Object.keys(this.bots).includes(name)) {
38+
throw new Error(`Invalid bot name ${name}`)
39+
}
40+
41+
if (this.clicks < this.bots[name].price) {
42+
return false;
43+
}
44+
45+
this.clicks -= this.bots[name].price;
46+
this.bots[name].purchased += 1;
47+
}
48+
49+
tick() {
50+
for (const bot in this.bots) {
51+
this.increment(this.bots[bot].purchased * this.bots[bot].increment);
52+
}
53+
}
54+
55+
get milestones() {
56+
return [
57+
{ clicks: 1000, unlock: "clickbots" },
58+
{ clicks: 5000, unlock: "bigbots" },
59+
];
60+
}
61+
}

0 commit comments

Comments
 (0)