Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe566ab88b | ||
|
|
e758605c3c | ||
|
|
08c2a70d10 | ||
|
|
f91de4ccfd | ||
|
|
4fdc52fcd1 | ||
|
|
019810615a | ||
|
|
c9f2f221ba |
@@ -0,0 +1,23 @@
|
|||||||
|
# Privacy Policy
|
||||||
|
|
||||||
|
LCDPet is an offline/local-first Android app.
|
||||||
|
|
||||||
|
## Data collection
|
||||||
|
|
||||||
|
LCDPet does not collect, transmit, sell, or share personal data.
|
||||||
|
|
||||||
|
## Network access
|
||||||
|
|
||||||
|
LCDPet does not request internet permission and does not connect to external servers.
|
||||||
|
|
||||||
|
## Local storage
|
||||||
|
|
||||||
|
LCDPet stores pet progress locally on the device.
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
LCDPet may request notification permission on supported Android versions. Notifications are used only for local pet care reminders.
|
||||||
|
|
||||||
|
## Third-party services
|
||||||
|
|
||||||
|
LCDPet does not use analytics, advertising SDKs, trackers, cloud services, or account systems.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# LCDPet
|
||||||
|
|
||||||
|
LCDPet is a tiny offline LCD-style virtual pet for Android.
|
||||||
|
|
||||||
|
It is designed to feel like a simple handheld digital pet: feed your pet, bathe it, let it nap, take it outside, handle Wants, and keep an eye on its care status.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Starter pet templates
|
||||||
|
- Offline/local-first virtual pet
|
||||||
|
- LCD-style toy-inspired interface
|
||||||
|
- Care actions: feed, bathe, nap, walk, potty, pet, and talk
|
||||||
|
- Random Wants and care reminders
|
||||||
|
- Optional Android notifications for pet care alerts
|
||||||
|
- No ads
|
||||||
|
- No tracking
|
||||||
|
- No internet permission
|
||||||
|
- No gameplay purchases or pay-to-win mechanics
|
||||||
|
|
||||||
|
## Privacy
|
||||||
|
|
||||||
|
LCDPet stores pet data locally on your device.
|
||||||
|
|
||||||
|
It does not use internet access, analytics, advertising SDKs, trackers, accounts, cloud sync, or external servers.
|
||||||
|
|
||||||
|
The notification permission is used only for local pet care reminders.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
LCDPet is licensed under the GNU General Public License v3.0.
|
||||||
|
|
||||||
|
See [LICENSE](LICENSE) for details.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Audio credits and license/source notes are included inside the app under:
|
||||||
|
|
||||||
|
`Credits / Licenses`
|
||||||
|
|
||||||
|
The audio credits source file is:
|
||||||
|
|
||||||
|
`app/src/main/assets/audio_credits.txt`
|
||||||
@@ -15,8 +15,8 @@ android {
|
|||||||
applicationId = "today.notfeelingit.lcdpet"
|
applicationId = "today.notfeelingit.lcdpet"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 1
|
versionCode = 2
|
||||||
versionName = "1.0"
|
versionName = "1.1"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|||||||
@@ -1,4 +1,17 @@
|
|||||||
LCDPet Audio Credits
|
LCDPet Credits / Licenses
|
||||||
|
|
||||||
|
LCDPet Software License
|
||||||
|
|
||||||
|
LCDPet is free software licensed under the GNU General Public License v3.0.
|
||||||
|
|
||||||
|
You may run, study, share, and modify LCDPet under the terms of that license.
|
||||||
|
|
||||||
|
Source code:
|
||||||
|
https://codeberg.org/KrisKS/LCDPet
|
||||||
|
|
||||||
|
The complete license text is included in the source repository's LICENSE file.
|
||||||
|
|
||||||
|
AUDIO CREDITS
|
||||||
|
|
||||||
Weather Channel music:
|
Weather Channel music:
|
||||||
“Calm Piano Jazz Loop” by ispeakwaves
|
“Calm Piano Jazz Loop” by ispeakwaves
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
LCDPET HOW TO
|
||||||
|
|
||||||
|
THE GOAL
|
||||||
|
|
||||||
|
LCDPet is a virtual pet that changes over time while you care for it.
|
||||||
|
|
||||||
|
Your goal is to build the strongest bond possible while keeping your pet healthy, happy, rested, clean, and cared for.
|
||||||
|
|
||||||
|
Pay attention to your pet's needs, respond at the right time, and avoid relying on the same action again and again.
|
||||||
|
|
||||||
|
Regular care matters. Your relationship with the pet grows through the choices you make over time.
|
||||||
|
|
||||||
|
CARING FOR YOUR PET
|
||||||
|
|
||||||
|
Watch the status bars and messages to see how your pet is doing.
|
||||||
|
|
||||||
|
When your pet needs something, choose the action that fits the situation.
|
||||||
|
|
||||||
|
Good care improves the Care record and helps Bond grow.
|
||||||
|
|
||||||
|
Missed needs, indoor accidents, overfeeding, sickness, and other harmful situations can increase Neglect and leave your pet in worse condition.
|
||||||
|
|
||||||
|
INSIDE AND OUTSIDE
|
||||||
|
|
||||||
|
Tap the Inside / Outside line near the top of the screen to change locations.
|
||||||
|
|
||||||
|
Inside is where most care and social actions happen.
|
||||||
|
|
||||||
|
Outside is where your pet can walk and safely use the bathroom.
|
||||||
|
|
||||||
|
Some situations are safe outside but can cause trouble indoors, so location matters.
|
||||||
|
|
||||||
|
CARE
|
||||||
|
|
||||||
|
BATHE
|
||||||
|
|
||||||
|
Bathing reduces Dirtiness and removes stains left by indoor accidents.
|
||||||
|
|
||||||
|
A pet with a stronger Bond accepts bathing more easily and may become fully clean.
|
||||||
|
|
||||||
|
Bathing also helps with recovery when extreme Dirtiness caused sickness.
|
||||||
|
|
||||||
|
FEED
|
||||||
|
|
||||||
|
Feeding lowers the Hunger value.
|
||||||
|
|
||||||
|
A high Hunger value means your pet needs food.
|
||||||
|
|
||||||
|
A very low Hunger value means your pet is already full.
|
||||||
|
|
||||||
|
Feeding an already full pet too many times can cause sickness from overfeeding, so pay attention to Hunger before feeding.
|
||||||
|
|
||||||
|
NAP
|
||||||
|
|
||||||
|
Napping restores Energy and helps your pet recover.
|
||||||
|
|
||||||
|
If Energy reaches zero, your pet may eventually fall asleep on its own.
|
||||||
|
|
||||||
|
Choosing an indoor nap is safer and calmer than letting your pet collapse from exhaustion.
|
||||||
|
|
||||||
|
SOCIALIZE
|
||||||
|
|
||||||
|
PET
|
||||||
|
|
||||||
|
Petting improves Happiness and can help Bond grow.
|
||||||
|
|
||||||
|
PLAY
|
||||||
|
|
||||||
|
Playing improves Happiness.
|
||||||
|
|
||||||
|
It can also use Energy and increase Hunger, so check the status bars afterward.
|
||||||
|
|
||||||
|
Using Play repeatedly can eventually increase Boredom instead of helping.
|
||||||
|
|
||||||
|
TALK
|
||||||
|
|
||||||
|
Press and hold TALK while speaking or making sounds.
|
||||||
|
|
||||||
|
The microphone reacts only to how loud the sound is.
|
||||||
|
|
||||||
|
LCDPet does not recognize words, create transcripts, save recordings, or upload audio.
|
||||||
|
|
||||||
|
Release TALK to finish.
|
||||||
|
|
||||||
|
OUTSIDE
|
||||||
|
|
||||||
|
WALK
|
||||||
|
|
||||||
|
Walking restores Health.
|
||||||
|
|
||||||
|
It also uses Energy and can increase Hunger and Dirtiness.
|
||||||
|
|
||||||
|
A pet that is exhausted, Weak, or Sick may not be able to walk.
|
||||||
|
|
||||||
|
POTTY
|
||||||
|
|
||||||
|
The Potty value increases over time and after meals.
|
||||||
|
|
||||||
|
Use Potty while outside to safely reset it.
|
||||||
|
|
||||||
|
If the value reaches its limit indoors, your pet can have an accident.
|
||||||
|
|
||||||
|
An indoor accident leaves a stain, increases Dirtiness, and adds Neglect.
|
||||||
|
|
||||||
|
Take your pet outside before the Potty value reaches its limit.
|
||||||
|
|
||||||
|
WANTS
|
||||||
|
|
||||||
|
Your pet may occasionally ask for something specific.
|
||||||
|
|
||||||
|
A Want can ask for Play, Pet, Talk, a Snack, a Bath, or a trip Outside.
|
||||||
|
|
||||||
|
Completing the request before it disappears gives extra Bond.
|
||||||
|
|
||||||
|
An ignored Want eventually expires, but it does not immediately harm your pet.
|
||||||
|
|
||||||
|
A Snack is a small treat and does not affect Hunger like a full meal.
|
||||||
|
|
||||||
|
BOND
|
||||||
|
|
||||||
|
Bond shows the strength of your relationship with your pet.
|
||||||
|
|
||||||
|
It grows through steady care, meeting Wants, and responding to needs.
|
||||||
|
|
||||||
|
Some Wants give more Bond than ordinary actions.
|
||||||
|
|
||||||
|
Using one action too many times can slow or reverse your progress.
|
||||||
|
|
||||||
|
The strongest Bond comes from understanding your pet and giving it balanced care.
|
||||||
|
|
||||||
|
STATUS BARS
|
||||||
|
|
||||||
|
HAPPINESS
|
||||||
|
|
||||||
|
Shows your pet's current mood.
|
||||||
|
|
||||||
|
ENERGY
|
||||||
|
|
||||||
|
Used by active actions such as Play and Walk.
|
||||||
|
|
||||||
|
Low Energy means your pet needs rest.
|
||||||
|
|
||||||
|
HUNGER
|
||||||
|
|
||||||
|
A high value means your pet needs food.
|
||||||
|
|
||||||
|
A low value means your pet is full.
|
||||||
|
|
||||||
|
DIRTINESS
|
||||||
|
|
||||||
|
Can increase through walking, outdoor time, rain, and accidents.
|
||||||
|
|
||||||
|
High Dirtiness creates a need for a bath and can eventually cause sickness.
|
||||||
|
|
||||||
|
POTTY
|
||||||
|
|
||||||
|
Increases over time and after meals.
|
||||||
|
|
||||||
|
Use Potty outdoors before an indoor accident happens.
|
||||||
|
|
||||||
|
BOREDOM
|
||||||
|
|
||||||
|
Can increase when the same action is used too many times.
|
||||||
|
|
||||||
|
Change activities and pay attention to what your pet needs.
|
||||||
|
|
||||||
|
HEALTH, SICKNESS, AND RECOVERY
|
||||||
|
|
||||||
|
Ignoring serious needs can make your pet Sick or Weak.
|
||||||
|
|
||||||
|
Possible causes include starvation, overfeeding, and extreme Dirtiness.
|
||||||
|
|
||||||
|
Messages near the pet tell you what is wrong.
|
||||||
|
|
||||||
|
Correct the cause before expecting the pet to recover.
|
||||||
|
|
||||||
|
Feed a starving pet.
|
||||||
|
|
||||||
|
Do not continue feeding an overfed pet.
|
||||||
|
|
||||||
|
Bathe a pet that became sick from Dirtiness.
|
||||||
|
|
||||||
|
Keep a Weak or recovering pet indoors.
|
||||||
|
|
||||||
|
Recovery takes time and may also require rest, food, and safe indoor conditions.
|
||||||
|
|
||||||
|
PET RECORD
|
||||||
|
|
||||||
|
The Pet Record shows:
|
||||||
|
|
||||||
|
Bond
|
||||||
|
The strength of your relationship.
|
||||||
|
|
||||||
|
Age
|
||||||
|
How long you have cared for your pet.
|
||||||
|
|
||||||
|
Care
|
||||||
|
The positive care you have provided.
|
||||||
|
|
||||||
|
Neglect
|
||||||
|
Missed needs and harmful situations.
|
||||||
|
|
||||||
|
Age means time together. It is not a countdown to death.
|
||||||
|
|
||||||
|
CARE JOURNAL
|
||||||
|
|
||||||
|
The Care Journal records important events in your pet's life.
|
||||||
|
|
||||||
|
It can show completed needs, missed needs, Wants, and other major care moments.
|
||||||
|
|
||||||
|
Read it to see how your pet has been treated over time.
|
||||||
|
|
||||||
|
CREDITS AND LICENSES
|
||||||
|
|
||||||
|
Tap Credits / Licenses near the top of the screen to view acknowledgements, sound credits, and license information.
|
||||||
|
|
||||||
|
HOW TO AND CREDITS CONTROLS
|
||||||
|
|
||||||
|
CLOSE returns to your pet.
|
||||||
|
|
||||||
|
MOVE places the MOVE and CLOSE buttons in another corner.
|
||||||
|
|
||||||
|
When you move the buttons in How To, they also move in Credits / Licenses, and vice versa.
|
||||||
@@ -33,8 +33,10 @@ data class LCDPetRecordSave(
|
|||||||
val isTradingInPet: Boolean = false,
|
val isTradingInPet: Boolean = false,
|
||||||
val isFindingNewPet: Boolean = false,
|
val isFindingNewPet: Boolean = false,
|
||||||
val tradeInProgress: Int = 0,
|
val tradeInProgress: Int = 0,
|
||||||
|
val tradeInStartedAtMs: Long = 0L,
|
||||||
val currentWant: String = "",
|
val currentWant: String = "",
|
||||||
val petName: String = "",
|
val petName: String = "",
|
||||||
|
val petTemplateId: String = "classic",
|
||||||
val isSleeping: Boolean = false,
|
val isSleeping: Boolean = false,
|
||||||
val sleepMode: String = "",
|
val sleepMode: String = "",
|
||||||
val roughWakeAlert: Boolean = false,
|
val roughWakeAlert: Boolean = false,
|
||||||
@@ -64,8 +66,10 @@ private object LCDPetSaveKeys {
|
|||||||
val IS_TRADING_IN_PET = booleanPreferencesKey("is_trading_in_pet")
|
val IS_TRADING_IN_PET = booleanPreferencesKey("is_trading_in_pet")
|
||||||
val IS_FINDING_NEW_PET = booleanPreferencesKey("is_finding_new_pet")
|
val IS_FINDING_NEW_PET = booleanPreferencesKey("is_finding_new_pet")
|
||||||
val TRADE_IN_PROGRESS = intPreferencesKey("trade_in_progress")
|
val TRADE_IN_PROGRESS = intPreferencesKey("trade_in_progress")
|
||||||
|
val TRADE_IN_STARTED_AT_MS = longPreferencesKey("trade_in_started_at_ms")
|
||||||
val CURRENT_WANT = stringPreferencesKey("current_want")
|
val CURRENT_WANT = stringPreferencesKey("current_want")
|
||||||
val PET_NAME = stringPreferencesKey("pet_name")
|
val PET_NAME = stringPreferencesKey("pet_name")
|
||||||
|
val PET_TEMPLATE_ID = stringPreferencesKey("pet_template_id")
|
||||||
val IS_SLEEPING = booleanPreferencesKey("is_sleeping")
|
val IS_SLEEPING = booleanPreferencesKey("is_sleeping")
|
||||||
val SLEEP_MODE = stringPreferencesKey("sleep_mode")
|
val SLEEP_MODE = stringPreferencesKey("sleep_mode")
|
||||||
val ROUGH_WAKE_ALERT = booleanPreferencesKey("rough_wake_alert")
|
val ROUGH_WAKE_ALERT = booleanPreferencesKey("rough_wake_alert")
|
||||||
@@ -97,8 +101,10 @@ val Context.lcdPetRecordSaveFlow: Flow<LCDPetRecordSave>
|
|||||||
isTradingInPet = preferences[LCDPetSaveKeys.IS_TRADING_IN_PET] ?: false,
|
isTradingInPet = preferences[LCDPetSaveKeys.IS_TRADING_IN_PET] ?: false,
|
||||||
isFindingNewPet = preferences[LCDPetSaveKeys.IS_FINDING_NEW_PET] ?: false,
|
isFindingNewPet = preferences[LCDPetSaveKeys.IS_FINDING_NEW_PET] ?: false,
|
||||||
tradeInProgress = preferences[LCDPetSaveKeys.TRADE_IN_PROGRESS] ?: 0,
|
tradeInProgress = preferences[LCDPetSaveKeys.TRADE_IN_PROGRESS] ?: 0,
|
||||||
|
tradeInStartedAtMs = preferences[LCDPetSaveKeys.TRADE_IN_STARTED_AT_MS] ?: 0L,
|
||||||
currentWant = preferences[LCDPetSaveKeys.CURRENT_WANT] ?: "",
|
currentWant = preferences[LCDPetSaveKeys.CURRENT_WANT] ?: "",
|
||||||
petName = preferences[LCDPetSaveKeys.PET_NAME] ?: "",
|
petName = preferences[LCDPetSaveKeys.PET_NAME] ?: "",
|
||||||
|
petTemplateId = preferences[LCDPetSaveKeys.PET_TEMPLATE_ID] ?: "classic",
|
||||||
isSleeping = preferences[LCDPetSaveKeys.IS_SLEEPING] ?: false,
|
isSleeping = preferences[LCDPetSaveKeys.IS_SLEEPING] ?: false,
|
||||||
sleepMode = preferences[LCDPetSaveKeys.SLEEP_MODE] ?: "",
|
sleepMode = preferences[LCDPetSaveKeys.SLEEP_MODE] ?: "",
|
||||||
roughWakeAlert = preferences[LCDPetSaveKeys.ROUGH_WAKE_ALERT] ?: false,
|
roughWakeAlert = preferences[LCDPetSaveKeys.ROUGH_WAKE_ALERT] ?: false,
|
||||||
@@ -129,8 +135,10 @@ suspend fun Context.saveLCDPetStats(
|
|||||||
isTradingInPet: Boolean,
|
isTradingInPet: Boolean,
|
||||||
isFindingNewPet: Boolean,
|
isFindingNewPet: Boolean,
|
||||||
tradeInProgress: Int,
|
tradeInProgress: Int,
|
||||||
|
tradeInStartedAtMs: Long = 0L,
|
||||||
currentWant: String,
|
currentWant: String,
|
||||||
petName: String,
|
petName: String,
|
||||||
|
petTemplateId: String = "classic",
|
||||||
isSleeping: Boolean,
|
isSleeping: Boolean,
|
||||||
sleepMode: String,
|
sleepMode: String,
|
||||||
roughWakeAlert: Boolean,
|
roughWakeAlert: Boolean,
|
||||||
@@ -158,8 +166,10 @@ suspend fun Context.saveLCDPetStats(
|
|||||||
preferences[LCDPetSaveKeys.IS_TRADING_IN_PET] = isTradingInPet
|
preferences[LCDPetSaveKeys.IS_TRADING_IN_PET] = isTradingInPet
|
||||||
preferences[LCDPetSaveKeys.IS_FINDING_NEW_PET] = isFindingNewPet
|
preferences[LCDPetSaveKeys.IS_FINDING_NEW_PET] = isFindingNewPet
|
||||||
preferences[LCDPetSaveKeys.TRADE_IN_PROGRESS] = tradeInProgress
|
preferences[LCDPetSaveKeys.TRADE_IN_PROGRESS] = tradeInProgress
|
||||||
|
preferences[LCDPetSaveKeys.TRADE_IN_STARTED_AT_MS] = tradeInStartedAtMs
|
||||||
preferences[LCDPetSaveKeys.CURRENT_WANT] = currentWant
|
preferences[LCDPetSaveKeys.CURRENT_WANT] = currentWant
|
||||||
preferences[LCDPetSaveKeys.PET_NAME] = petName
|
preferences[LCDPetSaveKeys.PET_NAME] = petName
|
||||||
|
preferences[LCDPetSaveKeys.PET_TEMPLATE_ID] = petTemplateId
|
||||||
preferences[LCDPetSaveKeys.IS_SLEEPING] = isSleeping
|
preferences[LCDPetSaveKeys.IS_SLEEPING] = isSleeping
|
||||||
preferences[LCDPetSaveKeys.SLEEP_MODE] = sleepMode
|
preferences[LCDPetSaveKeys.SLEEP_MODE] = sleepMode
|
||||||
preferences[LCDPetSaveKeys.ROUGH_WAKE_ALERT] = roughWakeAlert
|
preferences[LCDPetSaveKeys.ROUGH_WAKE_ALERT] = roughWakeAlert
|
||||||
|
|||||||
@@ -1,21 +1,8 @@
|
|||||||
package today.notfeelingit.lcdpet.ui.theme
|
package today.notfeelingit.lcdpet.ui.theme
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.darkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
|
|
||||||
private val DarkColorScheme = darkColorScheme(
|
|
||||||
primary = Purple80,
|
|
||||||
secondary = PurpleGrey80,
|
|
||||||
tertiary = Pink80
|
|
||||||
)
|
|
||||||
|
|
||||||
private val LightColorScheme = lightColorScheme(
|
private val LightColorScheme = lightColorScheme(
|
||||||
primary = Purple40,
|
primary = Purple40,
|
||||||
@@ -35,23 +22,10 @@ private val LightColorScheme = lightColorScheme(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LCDPetTheme(
|
fun LCDPetTheme(
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
|
||||||
// Dynamic color is available on Android 12+
|
|
||||||
dynamicColor: Boolean = true,
|
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
val colorScheme = when {
|
|
||||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
|
||||||
val context = LocalContext.current
|
|
||||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
darkTheme -> DarkColorScheme
|
|
||||||
else -> LightColorScheme
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = LightColorScheme,
|
||||||
typography = Typography,
|
typography = Typography,
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,170 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="108dp"
|
android:shape="rectangle">
|
||||||
android:height="108dp"
|
<solid android:color="#C6E2AD" />
|
||||||
android:viewportWidth="108"
|
</shape>
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M9,0L9,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,0L19,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,0L29,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
|
||||||
|
|||||||
@@ -1,30 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108">
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
<path android:fillColor="#789C60" android:pathData="M18,18 Q18,10 26,10 L82,10 Q90,10 90,18 L90,90 Q90,98 82,98 L26,98 Q18,98 18,90 Z"/>
|
||||||
<aapt:attr name="android:fillColor">
|
<path android:fillColor="#D3EBBC" android:pathData="M26,26 Q26,20 32,20 L76,20 Q82,20 82,26 L82,82 Q82,88 76,88 L32,88 Q26,88 26,82 Z"/>
|
||||||
<gradient
|
<path android:fillColor="#465F3A" android:pathData="M36,42 L44,42 L44,50 L36,50 Z"/>
|
||||||
android:endX="85.84757"
|
<path android:fillColor="#465F3A" android:pathData="M64,42 L72,42 L72,50 L64,50 Z"/>
|
||||||
android:endY="92.4963"
|
<path android:fillColor="#8CB074" android:pathData="M30,54 L36,54 L36,60 L30,60 Z"/>
|
||||||
android:startX="42.9492"
|
<path android:fillColor="#8CB074" android:pathData="M72,54 L78,54 L78,60 L72,60 Z"/>
|
||||||
android:startY="49.59793"
|
<path android:fillColor="#465F3A" android:pathData="M45,62 L63,62 L63,67 L45,67 Z"/>
|
||||||
android:type="linear">
|
<path android:fillColor="#465F3A" android:pathData="M38,78 L46,78 L46,83 L38,83 Z"/>
|
||||||
<item
|
<path android:fillColor="#465F3A" android:pathData="M62,78 L70,78 L70,83 L62,83 Z"/>
|
||||||
android:color="#44000000"
|
<path android:fillColor="#5A7A48" android:pathData="M49,11 Q49,8 52,8 L56,8 Q59,8 59,11 L59,18 L49,18 Z"/>
|
||||||
android:offset="0.0" />
|
</vector>
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
<background android:drawable="@drawable/ic_launcher_background" />
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 982 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
@@ -0,0 +1,3 @@
|
|||||||
|
Initial v1.0 release candidate.
|
||||||
|
|
||||||
|
Adds starter pet templates, the core LCDPet care loop, local save/load, Wants, care status tracking, optional local notifications, Credits / Licenses screen, and offline-first Android gameplay.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
LCDPet is a tiny offline LCD-style virtual pet for Android.
|
||||||
|
|
||||||
|
Feed your pet, bathe it, let it nap, take it outside, handle random Wants, and keep an eye on its care status. The app is designed around a simple handheld digital-pet feel with local progress, toy-like interactions, and a low-pressure care loop.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* Starter pet templates
|
||||||
|
|
||||||
|
* Offline/local-first virtual pet
|
||||||
|
* LCD-style toy-inspired interface
|
||||||
|
* Care actions including feed, bathe, nap, walk, potty, pet, and talk
|
||||||
|
* Random Wants and care reminders
|
||||||
|
* Optional Android notifications for local pet care alerts
|
||||||
|
* No ads
|
||||||
|
* No tracking
|
||||||
|
* No internet permission
|
||||||
|
* No gameplay purchases or pay-to-win mechanics
|
||||||
|
|
||||||
|
LCDPet stores pet data locally on your device. It does not use accounts, analytics, advertising SDKs, trackers, cloud sync, or external servers.
|
||||||
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1 @@
|
|||||||
|
Tiny offline LCD-style virtual pet for Android
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
LCDPet
|
||||||
@@ -11,9 +11,6 @@ pluginManagement {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plugins {
|
|
||||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
|
||||||
}
|
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||